]>
Commit | Line | Data |
---|---|---|
47baf534 | 1 | /* |
3e9b5b7b | 2 | * $Source$ |
3 | * $Author$ | |
4 | * $Header$ | |
47baf534 | 5 | * |
3e9b5b7b | 6 | * Copyright (C) 1987 by the Massachusetts Institute of Technology |
47baf534 | 7 | * |
3e9b5b7b | 8 | * Server for user registration with SMS and Kerberos. |
47baf534 | 9 | * |
803d15cb | 10 | * This program is a client of the Kerberos admin_server and a |
11 | * server for the userreg program. It is not a client of the | |
12 | * SMS server as it is linked with libsmsglue which bypasses | |
13 | * the network protocol. | |
47baf534 | 14 | */ |
15 | ||
16 | #ifndef lint | |
17 | static char *rcsid_reg_svr_c = "$Header$"; | |
18 | #endif lint | |
19 | ||
a640951a | 20 | #include "reg_svr.h" |
f46fccfa | 21 | #include "admin_server.h" |
007fdd80 | 22 | #include "admin_err.h" |
47baf534 | 23 | |
f46fccfa | 24 | extern int krb_err_base; |
25 | extern char admin_errmsg[]; | |
47baf534 | 26 | |
f3c010f8 | 27 | static char krbhst[BUFSIZ]; /* kerberos server name */ |
28 | static char krbrealm[REALM_SZ]; /* kerberos realm name */ | |
29 | ||
bac67528 | 30 | main(argc,argv) |
31 | int argc; | |
32 | char *argv[]; | |
47baf534 | 33 | { |
3e9b5b7b | 34 | struct msg message; /* Storage for parsed packet */ |
29bc4461 | 35 | int status = SUCCESS; /* Error status */ |
bac67528 | 36 | char retval[BUFSIZ]; /* Buffer to hold return message for client */ |
37 | ||
a640951a | 38 | void req_initialize(); /* Initialize request layer */ |
39 | void get_request(); /* Get a request */ | |
40 | void report(); /* Respond to a request */ | |
bac67528 | 41 | |
a640951a | 42 | /* Initialize */ |
bac67528 | 43 | whoami = argv[0]; |
a640951a | 44 | |
45 | /* Use com_err or output to stderr for all log messages. */ | |
46 | #ifdef DEBUG | |
47 | fprintf(stderr,"*** Debugging messages enabled. ***\n"); | |
48 | #endif DEBUG | |
49 | ||
3e9b5b7b | 50 | /* Error messages sent one line at a time */ |
f46fccfa | 51 | setlinebuf(stderr); |
47baf534 | 52 | |
29bc4461 | 53 | /* Initialize user registration error table for com_err */ |
47baf534 | 54 | init_ureg_err_tbl(); |
3e9b5b7b | 55 | |
3e9b5b7b | 56 | /* Connect to the SMS server */ |
57 | if ((status = sms_connect()) != SMS_SUCCESS) | |
58 | { | |
bac67528 | 59 | com_err(whoami, status, " on connect"); |
78eff417 | 60 | exit(1); |
61 | } | |
3e9b5b7b | 62 | |
63 | /* Authorize, telling the server who you are */ | |
bac67528 | 64 | if ((status = sms_auth(whoami)) != SMS_SUCCESS) |
3e9b5b7b | 65 | { |
bac67528 | 66 | com_err(whoami, status, " on auth"); |
78eff417 | 67 | exit(1); |
68 | } | |
a640951a | 69 | |
f3c010f8 | 70 | if (status = get_krbrlm(krbrealm, 1)) { |
71 | status += krb_err_base; | |
72 | com_err(whoami, status, " fetching kerberos realm"); | |
73 | exit(1); | |
74 | } | |
a640951a | 75 | |
f3c010f8 | 76 | if (status = get_krbhst(krbhst, krbrealm, 1)) { |
77 | status += krb_err_base; | |
78 | com_err(whoami, status, " fetching kerberos hostname"); | |
79 | exit(1); | |
80 | } else { | |
81 | char *s; | |
82 | for (s = krbhst; *s && *s != '.'; s++) | |
83 | if (isupper(*s)) | |
84 | *s = tolower(*s); | |
85 | *s = 0; | |
86 | } | |
0349fd4d | 87 | |
88 | journal = fopen(JOURNAL, "a"); | |
89 | if (journal == NULL) { | |
90 | com_err(whoami, errno, " while opening journal file"); | |
91 | exit(1); | |
92 | } | |
a640951a | 93 | |
94 | /* Allow request layer to initialize */ | |
95 | req_initialize(); | |
96 | ||
3e9b5b7b | 97 | /* Sit around waiting for requests from the client. */ |
98 | for (;;) | |
99 | { | |
a640951a | 100 | get_request(&message); |
3e9b5b7b | 101 | |
3e9b5b7b | 102 | switch((int)message.request) |
103 | { | |
104 | case UREG_VERIFY_USER: | |
bac67528 | 105 | status = verify_user(&message,retval); |
47baf534 | 106 | break; |
3e9b5b7b | 107 | case UREG_RESERVE_LOGIN: |
bac67528 | 108 | status = reserve_user(&message,retval); |
47baf534 | 109 | break; |
3e9b5b7b | 110 | case UREG_SET_PASSWORD: |
bac67528 | 111 | status = set_password(&message,retval); |
47baf534 | 112 | break; |
113 | ||
3e9b5b7b | 114 | default: |
47baf534 | 115 | status = UREG_UNKNOWN_REQUEST; |
a640951a | 116 | critical_alert(FAIL_INST,"Unknown request %d from userreg.", |
117 | message.request); | |
47baf534 | 118 | break; |
119 | } | |
47baf534 | 120 | |
3e9b5b7b | 121 | /* Report what happened to client */ |
a640951a | 122 | report(status, retval); |
47baf534 | 123 | } |
124 | } | |
125 | ||
eb39a9ea | 126 | /* This is necessary so that this server can know where to put its |
127 | tickets. */ | |
128 | char *tkt_string() | |
129 | { | |
130 | return("/tmp/tkt_ureg"); | |
131 | } | |
132 | ||
bac67528 | 133 | int parse_encrypted(message,data) |
3e9b5b7b | 134 | struct msg *message; /* Formatted packet */ |
bac67528 | 135 | struct db_data *data; /* Data from the SMS database */ |
3e9b5b7b | 136 | /* This routine makes sure that the ID from the database matches |
137 | the ID sent accross in the packet. The information in the packet | |
138 | was created in the following way: | |
139 | ||
803d15cb | 140 | The plain text ID number was encrypted via EncryptID() resulting |
141 | in the form that would appear in the SMS database. This is | |
29bc4461 | 142 | concatinated to the plain text ID so that the ID string contains plain |
143 | text ID followed by a null followed by the encrypted ID. Other | |
144 | information such as the username or password is appended. The whole | |
145 | thing is then DES encrypted using the encrypted ID as the source of | |
146 | the key. | |
3e9b5b7b | 147 | |
148 | This routine tries each encrypted ID in the database that belongs | |
149 | to someone with this user's first and last name and tries to | |
bac67528 | 150 | decrypt the packet with this information. If it succeeds, it returns |
29bc4461 | 151 | zero and initializes all the fields of the formatted packet structure |
152 | that depend on the encrypted information. */ | |
47baf534 | 153 | { |
3e9b5b7b | 154 | C_Block key; /* The key for DES en/decryption */ |
155 | Key_schedule sched; /* En/decryption schedule */ | |
156 | static char decrypt[BUFSIZ]; /* Buffer to hold decrypted information */ | |
157 | long decrypt_len; /* Length of decypted ID information */ | |
158 | char recrypt[14]; /* Buffer to hold re-encrypted information */ | |
159 | static char hashid[14]; /* Buffer to hold one-way encrypted ID */ | |
160 | char idnumber[BUFSIZ]; /* Buffer to hold plain-text ID */ | |
bac67528 | 161 | char *temp; /* A temporary string pointer */ |
162 | int len; /* Keeps track of length left in packet */ | |
29bc4461 | 163 | int status = SUCCESS; /* Error status */ |
3e9b5b7b | 164 | |
bac67528 | 165 | #ifdef DEBUG |
166 | com_err(whoami,0,"Entering parse_encrypted"); | |
167 | #endif | |
168 | ||
3e9b5b7b | 169 | /* Make the decrypted information length the same as the encrypted |
170 | information length. Both are integral multples of eight bytes | |
171 | because of the DES encryption routines. */ | |
bac67528 | 172 | decrypt_len = (long)message->encrypted_len; |
47baf534 | 173 | |
3e9b5b7b | 174 | /* Get key from the one-way encrypted ID in the SMS database */ |
bac67528 | 175 | string_to_key(data->mit_id, key); |
3e9b5b7b | 176 | /* Get schedule from key */ |
47baf534 | 177 | key_sched(key, sched); |
3e9b5b7b | 178 | /* Decrypt information from packet using this key. Since decrypt_len |
179 | is an integral multiple of eight bytes, it will probably be null- | |
180 | padded. */ | |
bac67528 | 181 | pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, DECRYPT); |
3e9b5b7b | 182 | |
183 | /* Extract the plain text and encrypted ID fields from the decrypted | |
184 | packet information. */ | |
185 | /* Since the decrypted information starts with the plain-text ID | |
186 | followed by a null, if the decryption worked, this will only | |
187 | copy the plain text part of the decrypted information. It is | |
188 | important that strncpy be used because if we are not using the | |
189 | correct key, there is no guarantee that a null will occur | |
190 | anywhere in the string. */ | |
29bc4461 | 191 | (void) strncpy(idnumber,decrypt,(int)decrypt_len); |
3e9b5b7b | 192 | /* Point temp to the end of the plain text ID number. */ |
47baf534 | 193 | temp = decrypt + strlen(idnumber) + 1; |
29bc4461 | 194 | /* Find out how much more packet there is. */ |
bac67528 | 195 | len = message->encrypted_len - (temp - decrypt); |
29bc4461 | 196 | /* Copy the next CRYPT_LEN bytes of the decrypted information into |
197 | hashid if there are CRYPT_LEN more bytes to copy. There will be | |
3e9b5b7b | 198 | if we have the right key. */ |
29bc4461 | 199 | (void) strncpy(hashid, temp, min(len, CRYPT_LEN)); |
3e9b5b7b | 200 | /* Point temp to the end of the encrypted ID field */ |
47baf534 | 201 | temp += strlen(hashid) + 1; |
3e9b5b7b | 202 | /* Find out how much more room there is. */ |
bac67528 | 203 | len = message->encrypted_len - (temp - decrypt); |
3e9b5b7b | 204 | |
bac67528 | 205 | /* Now compare encrypted ID's don't match. */ |
803d15cb | 206 | if (strcmp(hashid, data->mit_id)) status = FAILURE; |
29bc4461 | 207 | if (status == SUCCESS) |
3e9b5b7b | 208 | { |
803d15cb | 209 | EncryptID(recrypt, idnumber, message->first, message->last); |
bac67528 | 210 | /* Now compare encrypted plain text to ID from database. */ |
803d15cb | 211 | if (strcmp(recrypt, data->mit_id)) status = FAILURE; |
47baf534 | 212 | } |
3e9b5b7b | 213 | |
29bc4461 | 214 | if (status == SUCCESS) |
bac67528 | 215 | { |
216 | /* We made it. Now we can finish initializing message. */ | |
217 | /* Point leftover to whatever is left over! */ | |
218 | message->leftover = temp; | |
219 | message->leftover_len = len; | |
220 | /* Since we know we have the right user, fill in the information | |
221 | from the SMS database. */ | |
222 | message->db.reg_status = data->reg_status; | |
29bc4461 | 223 | (void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid)); |
224 | (void) strncpy(message->db.mit_id,data->mit_id, | |
225 | sizeof(message->db.mit_id)); | |
226 | (void) strncpy(message->db.login,data->login, sizeof(message->db.login)); | |
bac67528 | 227 | } |
47baf534 | 228 | |
bac67528 | 229 | #ifdef DEBUG |
230 | if (status) | |
29bc4461 | 231 | com_err(whoami,status," parse_encrypted failed."); |
bac67528 | 232 | else |
29bc4461 | 233 | com_err(whoami,status,"parse_encrypted succeeded."); |
bac67528 | 234 | #endif |
47baf534 | 235 | |
47baf534 | 236 | return status; |
237 | } | |
238 | ||
bac67528 | 239 | int db_callproc(argc,argv,queue) |
240 | int argc; /* Number of arguments returned by SMS */ | |
241 | char *argv[]; /* Arguments returned by SMS */ | |
242 | struct save_queue *queue; /* Queue to save information in */ | |
243 | /* This function is called by sms_query after each tuple found. It is | |
29bc4461 | 244 | used by find_user to cache information about each user found. */ |
47baf534 | 245 | { |
bac67528 | 246 | struct db_data *data; /* Structure to store the information in */ |
29bc4461 | 247 | int status = SUCCESS; /* Error status */ |
47baf534 | 248 | |
bac67528 | 249 | #ifdef DEBUG |
250 | com_err(whoami,0,"Entering db_callproc."); | |
251 | #endif | |
252 | ||
29bc4461 | 253 | if (argc != U_END) |
3e9b5b7b | 254 | { |
a640951a | 255 | critical_alert |
256 | (FAIL_INST, | |
257 | "Wrong number of arguments returned from get_user_by_name."); | |
803d15cb | 258 | status = SMS_ABORT; |
f46fccfa | 259 | } |
bac67528 | 260 | else |
3e9b5b7b | 261 | { |
bac67528 | 262 | /* extract the needed information from the results of the SMS query */ |
263 | data = (struct db_data *)malloc(sizeof(struct db_data)); | |
29bc4461 | 264 | data->reg_status = atoi(argv[U_STATE]); |
265 | (void) strncpy(data->login,argv[U_NAME],sizeof(data->login)); | |
266 | (void) strncpy(data->mit_id,argv[U_MITID],sizeof(data->mit_id)); | |
267 | (void) strncpy(data->uid,argv[U_UID],sizeof(data->uid)); | |
bac67528 | 268 | #ifdef DEBUG |
269 | fprintf(stderr,"Found in database:\n"); | |
270 | fprintf(stderr," Registration status: %d\n",data->reg_status); | |
271 | fprintf(stderr," login: %s\n",data->login); | |
272 | fprintf(stderr," MIT ID: %s\n",data->mit_id); | |
273 | fprintf(stderr," uid: %s\n",data->uid); | |
274 | #endif | |
275 | sq_save_data(queue,data); | |
47baf534 | 276 | } |
bac67528 | 277 | |
278 | return status; | |
279 | } | |
3e9b5b7b | 280 | |
bac67528 | 281 | int find_user(message) |
282 | struct msg *message; /* Formatted packet structure */ | |
283 | /* This routine verifies that a user is allowed to register by finding | |
284 | him/her in the SMS database. It returns the status of the SMS | |
285 | query that it calls. */ | |
286 | { | |
803d15cb | 287 | #define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */ |
bac67528 | 288 | char *q_name; /* Name of query */ |
29bc4461 | 289 | int q_argc; /* Number of arguments for query */ |
290 | char *q_argv[GUBN_ARGS]; /* Arguments to query */ | |
291 | int status = SUCCESS; /* Query return status */ | |
bac67528 | 292 | |
293 | struct save_queue *queue; /* Queue to hold SMS data */ | |
294 | struct db_data *data; /* Structure for data for one tuple */ | |
29bc4461 | 295 | short verified = FALSE; /* Have we verified the user? */ |
bac67528 | 296 | |
297 | /* Zero the mit_id field in the formatted packet structure. This | |
298 | being zeroed means that no user was found. */ | |
299 | bzero(message->db.mit_id,sizeof(message->db.mit_id)); | |
300 | ||
29bc4461 | 301 | if (status == SUCCESS) |
3e9b5b7b | 302 | { |
bac67528 | 303 | /* Get ready to make an SMS query */ |
304 | q_name = "get_user_by_name"; | |
29bc4461 | 305 | q_argc = GUBN_ARGS; /* #defined in this routine */ |
bac67528 | 306 | q_argv[0] = message->first; |
307 | q_argv[1] = message->last; | |
308 | ||
309 | /* Create queue to hold information */ | |
310 | queue = sq_create(); | |
311 | ||
312 | /* Do it */ | |
313 | status = sms_query(q_name,q_argc,q_argv,db_callproc,(char *)queue); | |
314 | ||
315 | #ifdef DEBUG | |
803d15cb | 316 | fprintf(stderr," %d returned by get_user_by_name\n",status); |
bac67528 | 317 | #endif |
318 | ||
319 | if (status == SMS_SUCCESS) | |
320 | { | |
321 | /* Traverse the list, freeing data as we go. If sq_get_data() | |
322 | returns zero if there is no more data on the queue. */ | |
323 | while (sq_get_data(queue,&data)) | |
324 | { | |
325 | if (!verified) | |
326 | /* parse_encrypted returns zero on success */ | |
29bc4461 | 327 | verified = (parse_encrypted(message,data) == SUCCESS); |
328 | free((char *)data); | |
bac67528 | 329 | } |
330 | } | |
29bc4461 | 331 | |
332 | /* Destroy the queue */ | |
333 | sq_destroy(queue); | |
47baf534 | 334 | } |
47baf534 | 335 | |
bac67528 | 336 | #ifdef DEBUG |
337 | fprintf(stderr,"Returned from find_user\n"); | |
338 | fprintf(stderr," MIT ID: %s\n", message->db.mit_id); | |
339 | fprintf(stderr," Registration status: %d\n",message->db.reg_status); | |
340 | fprintf(stderr," uid: %s\n",message->db.uid); | |
341 | fprintf(stderr," login: %s\n",message->db.login); | |
342 | fprintf(stderr," Status from query: %d\n",status); | |
343 | #endif DEBGUG | |
344 | ||
345 | return status; | |
346 | } | |
347 | ||
bac67528 | 348 | int verify_user(message,retval) |
3e9b5b7b | 349 | struct msg *message; |
bac67528 | 350 | char *retval; |
29bc4461 | 351 | /* This routine determines whether a user is in the databse and returns |
352 | his state so that other routines can figure out whether he is the | |
353 | correct state for various transactions. */ | |
354 | ||
47baf534 | 355 | { |
29bc4461 | 356 | int status = SUCCESS; /* Return status */ |
bac67528 | 357 | |
358 | /* Log that we are about to veryify user */ | |
359 | com_err(whoami,0,"verify_user %s %s",message->first,message->last); | |
360 | ||
361 | /* Figure out what user (if any) can be found based on the | |
362 | encrypted information in the packet. (See the comment on | |
363 | parse_encrypted().) */ | |
bac67528 | 364 | |
365 | status = find_user(message); | |
366 | ||
367 | /* If SMS coudn't find the user */ | |
368 | if (status == SMS_NO_MATCH) | |
f46fccfa | 369 | status = UREG_USER_NOT_FOUND; |
bac67528 | 370 | else if (status == SMS_SUCCESS) |
3e9b5b7b | 371 | { |
bac67528 | 372 | /* If the information sent over in the packet did not point to a |
373 | valid user, the mit_id field in the formatted packet structure | |
374 | will be empty. */ | |
29bc4461 | 375 | if (message->db.mit_id[0] == NULL) |
bac67528 | 376 | status = UREG_USER_NOT_FOUND; |
377 | /* If the user was found but the registration has already started, | |
378 | use this as the status */ | |
379 | else | |
380 | { | |
381 | switch (message->db.reg_status) | |
382 | { | |
29bc4461 | 383 | case US_NO_LOGIN_YET: |
bac67528 | 384 | status = SUCCESS; |
385 | break; | |
29bc4461 | 386 | case US_REGISTERED: |
bac67528 | 387 | status = UREG_ALREADY_REGISTERED; |
388 | break; | |
29bc4461 | 389 | case US_NO_PASSWD: |
bac67528 | 390 | status = UREG_NO_PASSWD_YET; |
391 | break; | |
29bc4461 | 392 | case US_DELETED: |
bac67528 | 393 | status = UREG_DELETED; |
394 | break; | |
29bc4461 | 395 | case US_NOT_ALLOWED: |
bac67528 | 396 | status = UREG_NOT_ALLOWED; |
397 | break; | |
29bc4461 | 398 | |
bac67528 | 399 | default: |
400 | status = UREG_MISC_ERROR; | |
a640951a | 401 | critical_alert(FAIL_INST,"Bad user state for login %s.", |
402 | message->db.login); | |
bac67528 | 403 | break; |
404 | } | |
405 | /* Set retval to the login name so that the client can use | |
406 | it in the error message it will give the user. */ | |
29bc4461 | 407 | (void) strcpy(retval,message->db.login); |
bac67528 | 408 | } |
47baf534 | 409 | } |
3e9b5b7b | 410 | |
29bc4461 | 411 | com_err(whoami,status," returned from verify_user"); |
bac67528 | 412 | |
47baf534 | 413 | return status; |
414 | } | |
bac67528 | 415 | |
416 | int ureg_get_tkt() | |
47baf534 | 417 | { |
29bc4461 | 418 | int status = SUCCESS; /* Return status */ |
bac67528 | 419 | |
420 | /* Get keys for interacting with Kerberos admin server. */ | |
f3c010f8 | 421 | /* principal, instance, realm, service, service instance, life, file */ |
422 | if (status = get_svc_in_tkt("register", "sms", krbrealm, "changepw", | |
423 | krbhst, 1, KEYFILE)) | |
bac67528 | 424 | status += krb_err_base; |
425 | ||
803d15cb | 426 | #ifdef DEBUG |
427 | if (status == SUCCESS) | |
428 | com_err(whoami,status,"Succeeded in getting tickets."); | |
429 | else | |
430 | com_err(whoami,status,"Failed to get tickets."); | |
431 | #endif | |
bac67528 | 432 | return status; |
47baf534 | 433 | } |
434 | ||
bac67528 | 435 | int null_callproc(argc,argv,message) |
436 | int argc; | |
437 | char *argv[]; | |
3e9b5b7b | 438 | char *message; |
bac67528 | 439 | /* This routine is a null callback that should be used for queries that |
440 | do not return tuples. If it ever gets called, something is wrong. */ | |
47baf534 | 441 | { |
a640951a | 442 | critical_alert(FAIL_INST,"Something returned from an update query."); |
803d15cb | 443 | return FAILURE; |
47baf534 | 444 | } |
445 | ||
bac67528 | 446 | int do_admin_call(login, passwd, uid) |
29bc4461 | 447 | char *login; /* Requested kerberos principal */ |
448 | char *passwd; /* Requested password */ | |
449 | char *uid; /* Uid of user who owns this principal */ | |
450 | /* This routine gets tickets, makes the appropriate call to admin_call, | |
451 | and destroys tickets. */ | |
47baf534 | 452 | { |
bac67528 | 453 | int status; /* Error status */ |
454 | char uid_buf[20]; /* Holds uid for kerberos */ | |
455 | ||
803d15cb | 456 | com_err(whoami,0,"Entering do_admin_call"); |
457 | ||
bac67528 | 458 | if ((status = ureg_get_tkt()) == SUCCESS) |
3e9b5b7b | 459 | { |
bac67528 | 460 | /* Try to reserve kerberos principal. To do this, send a |
461 | password request and a null password. It will only succeed | |
462 | if there is no principal or the principal exists and has no | |
463 | password. */ | |
803d15cb | 464 | /* 13 chars of placebo for backwards-compatability - the admin |
465 | server protocol reqires this. */ | |
bac67528 | 466 | bzero(uid_buf,sizeof(uid_buf)); |
f3c010f8 | 467 | (void) sprintf(uid_buf, "%13s", uid); |
bac67528 | 468 | |
469 | if ((status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, login, | |
470 | "", passwd, uid_buf)) != KSUCCESS) | |
3e9b5b7b | 471 | { |
29bc4461 | 472 | com_err(whoami,status," server error: %s",admin_errmsg); |
bac67528 | 473 | |
474 | if (strcmp(admin_errmsg, | |
475 | "Principal already in kerberos database.") == 0) | |
476 | status = UREG_KRB_TAKEN; | |
a640951a | 477 | critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.", |
478 | login); | |
47baf534 | 479 | } |
47baf534 | 480 | } |
bac67528 | 481 | |
482 | dest_tkt(); | |
803d15cb | 483 | com_err(whoami,status," returned from do_adin_call"); |
bac67528 | 484 | return status; |
47baf534 | 485 | } |
3e9b5b7b | 486 | |
bac67528 | 487 | int reserve_user(message,retval) |
488 | struct msg *message; | |
489 | char *retval; | |
47baf534 | 490 | { |
bac67528 | 491 | int q_argc; /* Number of arguments to query */ |
492 | char *q_argv[3]; /* Arguments to SMS query */ | |
493 | char *q_name; /* Name of SMS query */ | |
29bc4461 | 494 | int status = SUCCESS; /* General purpose error status */ |
bac67528 | 495 | char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */ |
496 | char *login; /* The login name the user wants */ | |
497 | register int i; /* A counter */ | |
bac67528 | 498 | |
803d15cb | 499 | /* Log that we are about to reserve a user. */ |
29bc4461 | 500 | com_err(whoami, 0, "reserve_user %s %s", |
bac67528 | 501 | message->first, message->last); |
3e9b5b7b | 502 | |
bac67528 | 503 | /* Check to make sure that we can verify this user. */ |
504 | if ((status = verify_user(message,retval)) == SUCCESS) | |
3e9b5b7b | 505 | { |
29bc4461 | 506 | /* Get the requested login name from leftover packet information. */ |
bac67528 | 507 | login = message->leftover; |
29bc4461 | 508 | |
509 | /* Check the login name for validity. The login name is currently | |
510 | is allowed to contain lowercase letters and numbers in any | |
511 | position and underscore characters and periods in any position | |
512 | but the first. */ | |
513 | if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME)) | |
bac67528 | 514 | status = UREG_INVALID_UNAME; |
47baf534 | 515 | } |
29bc4461 | 516 | if (status == SUCCESS) |
5fff8167 | 517 | if (login[1] == '_') |
29bc4461 | 518 | status = UREG_INVALID_UNAME; |
519 | if (status == SUCCESS) | |
3e9b5b7b | 520 | { |
803d15cb | 521 | for (i = 0; i < strlen(login); i++) |
5fff8167 | 522 | if (!islower(login[i]) && !isdigit(login[i]) && |
523 | (login[i] != '_')) | |
803d15cb | 524 | { |
525 | status = UREG_INVALID_UNAME; | |
526 | break; | |
527 | } | |
47baf534 | 528 | } |
29bc4461 | 529 | if (status == SUCCESS) |
3e9b5b7b | 530 | { |
bac67528 | 531 | /* Now that we have a valid user with a valid login... */ |
532 | ||
533 | /* First, try to reserve the user in SMS. */ | |
29bc4461 | 534 | (void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT); |
bac67528 | 535 | q_name = "register_user"; |
536 | q_argv[0] = message->db.uid; | |
537 | q_argv[1] = login; | |
538 | q_argv[2] = fstype_buf; | |
539 | q_argc = 3; | |
29bc4461 | 540 | status = sms_query(q_name,q_argc,q_argv,null_callproc,(char *)0); |
bac67528 | 541 | switch (status) |
542 | { | |
543 | case SMS_SUCCESS: | |
544 | status = SUCCESS; | |
545 | break; | |
546 | case SMS_IN_USE: | |
547 | status = UREG_LOGIN_USED; | |
548 | break; | |
549 | default: | |
550 | status = UREG_MISC_ERROR; | |
a640951a | 551 | critical_alert(FAIL_INST,"%s returned from register_user.", |
552 | error_message(status)); | |
bac67528 | 553 | break; |
554 | } | |
47baf534 | 555 | } |
29bc4461 | 556 | if (status == SUCCESS) |
3e9b5b7b | 557 | { |
bac67528 | 558 | /* SMS login was successfully created; try to reserve kerberos |
559 | principal. */ | |
29bc4461 | 560 | /* If this routine fails, store the login in the retval so |
bac67528 | 561 | that it can be used in the client-side error message. */ |
562 | if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS) | |
29bc4461 | 563 | (void) strcpy(retval, login); |
47baf534 | 564 | } |
bac67528 | 565 | |
29bc4461 | 566 | com_err(whoami, status, " returned from reserve_user"); |
bac67528 | 567 | |
47baf534 | 568 | return status; |
bac67528 | 569 | } |
47baf534 | 570 | |
bac67528 | 571 | int set_final_status(login) |
572 | char *login; | |
803d15cb | 573 | /* This routine updates a user's registration status to fully |
29bc4461 | 574 | registered. */ |
47baf534 | 575 | { |
bac67528 | 576 | char *q_name; /* Name of SMS query */ |
577 | int q_argc; /* Number of arguments for SMS query */ | |
578 | char *q_argv[2]; /* Arguments to get user by uid */ | |
29bc4461 | 579 | char state[7]; /* Can hold a 16 bit integer */ |
bac67528 | 580 | int status; /* Error status */ |
581 | ||
582 | com_err(whoami, 0, "Setting final status for %s", login); | |
583 | ||
29bc4461 | 584 | (void) sprintf(state,"%d",US_REGISTERED); |
bac67528 | 585 | q_name = "update_user_status"; |
586 | q_argc = 2; | |
587 | q_argv[0] = login; | |
29bc4461 | 588 | q_argv[1] = state; |
bac67528 | 589 | if ((status = sms_query(q_name, q_argc, q_argv, null_callproc, |
590 | (char *)0)) != SMS_SUCCESS) | |
a640951a | 591 | critical_alert(FAIL_INST,"%s returned from update_user_status.", |
592 | error_message(status)); | |
3e9b5b7b | 593 | |
29bc4461 | 594 | com_err(whoami,status," returned from set_final_status"); |
f46fccfa | 595 | return status; |
bac67528 | 596 | } |
f46fccfa | 597 | |
bac67528 | 598 | |
599 | int set_password(message,retval) | |
600 | struct msg *message; | |
601 | char *retval; | |
602 | /* This routine is used to set the initial password for the new user. */ | |
47baf534 | 603 | { |
29bc4461 | 604 | int status = SUCCESS; /* Return status */ |
bac67528 | 605 | char *passwd; /* User's password */ |
bac67528 | 606 | |
29bc4461 | 607 | com_err(whoami, 0, " set_password %s %s", |
bac67528 | 608 | message->first, message->last); |
609 | ||
610 | status = verify_user(message,retval); | |
611 | ||
612 | /* Don't set the password unless the registration status of the user | |
613 | is that he exists and has no password. */ | |
614 | if (status == SUCCESS) | |
615 | status = UREG_NO_LOGIN_YET; | |
616 | if (status == UREG_NO_PASSWD_YET) | |
3e9b5b7b | 617 | { |
bac67528 | 618 | /* User is in proper state for this transaction. */ |
619 | ||
620 | passwd = message->leftover; | |
621 | ||
622 | /* Set password. */ | |
623 | if ((status = do_admin_call(message->db.login, | |
624 | passwd, message->db.uid)) != SUCCESS) | |
625 | /* If failure, allow login name to be used in client | |
626 | error message */ | |
29bc4461 | 627 | (void) strcpy(retval,message->db.login); |
bac67528 | 628 | else |
629 | /* Otherwise, mark user as finished. */ | |
630 | status = set_final_status(message->db.login); | |
631 | } | |
29bc4461 | 632 | com_err(whoami, status, " returned from set_passwd"); |
47baf534 | 633 | |
bac67528 | 634 | return status; |
635 | } | |
47baf534 | 636 | |
47baf534 | 637 | /* |
638 | * Local Variables: | |
639 | * mode: c | |
3e9b5b7b | 640 | * c-argdecl-indent: 2 |
47baf534 | 641 | * c-brace-offset: -4 |
bac67528 | 642 | * c-continued-statement-offset: 4 |
3e9b5b7b | 643 | * c-indent-level: 4 |
644 | * c-label-offset: -2 | |
47baf534 | 645 | * End: |
646 | */ |