* $Author$
* $Header$
*
- * Copyright (C) 1987 by the Massachusetts Institute of Technology
+ * Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*
- * Server for user registration with SMS and Kerberos.
+ * Server for user registration with Moira and Kerberos.
*
* This program is a client of the Kerberos admin_server and a
* server for the userreg program. It is not a client of the
- * SMS server as it is linked with libsmsglue which bypasses
+ * Moira server as it is linked with libsmsglue which bypasses
* the network protocol.
*/
static char *rcsid_reg_svr_c = "$Header$";
#endif lint
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <krb.h>
+#include <des.h>
+#include <kadm.h>
+#include <kadm_err.h>
+#include <krb_err.h>
+#include <errno.h>
+#include "sms.h"
+#include "sms_app.h"
#include "reg_svr.h"
-#include "admin_server.h"
-#include "admin_err.h"
-extern int krb_err_base;
extern char admin_errmsg[];
-static char krbhst[BUFSIZ]; /* kerberos server name */
-static char krbrealm[REALM_SZ]; /* kerberos realm name */
+void reg_com_err_hook();
main(argc,argv)
int argc;
/* Initialize */
whoami = argv[0];
- /* Use com_err or output to stderr for all log messages. */
-#ifdef DEBUG
- fprintf(stderr,"*** Debugging messages enabled. ***\n");
-#endif DEBUG
-
/* Error messages sent one line at a time */
setlinebuf(stderr);
+ setlinebuf(stdout);
+ set_com_err_hook(reg_com_err_hook);
- /* Initialize user registration error table for com_err */
+ /* Initialize com_err error tables */
init_ureg_err_tbl();
+ init_krb_err_tbl();
+ init_kadm_err_tbl();
- /* Connect to the SMS server */
- if ((status = sms_connect()) != SMS_SUCCESS)
+ /* Use com_err or output to stderr for all log messages. */
+#ifdef DEBUG
+ com_err(whoami, 0, "*** Debugging messages enabled. ***");
+#endif DEBUG
+
+ /* Set the name of our kerberos ticket file */
+ krb_set_tkt_string("/tmp/tkt_ureg");
+
+ /* Connect to the Moira server */
+ if ((status = sms_connect(SMS_SERVER)) != SMS_SUCCESS)
{
- com_err(whoami, status, " on connect");
+ com_err(whoami, status, " on sms_connect");
exit(1);
}
/* Authorize, telling the server who you are */
if ((status = sms_auth(whoami)) != SMS_SUCCESS)
{
- com_err(whoami, status, " on auth");
- exit(1);
- }
-
- if (status = get_krbrlm(krbrealm, 1)) {
- status += krb_err_base;
- com_err(whoami, status, " fetching kerberos realm");
+ com_err(whoami, status, " on sms_auth");
exit(1);
}
- if (status = get_krbhst(krbhst, krbrealm, 1)) {
- status += krb_err_base;
- com_err(whoami, status, " fetching kerberos hostname");
- exit(1);
- } else {
- char *s;
- for (s = krbhst; *s && *s != '.'; s++)
- if (isupper(*s))
- *s = tolower(*s);
- *s = 0;
- }
-
- journal = fopen(JOURNAL, "a");
+ journal = fopen(REGJOURNAL, "a");
if (journal == NULL) {
com_err(whoami, errno, " while opening journal file");
exit(1);
status = reserve_user(&message,retval);
break;
case UREG_SET_PASSWORD:
+ case UREG_GET_KRB:
status = set_password(&message,retval);
break;
-
+ case UREG_SET_IDENT:
+ status = set_identity(&message,retval);
+ break;
default:
status = UREG_UNKNOWN_REQUEST;
critical_alert(FAIL_INST,"Unknown request %d from userreg.",
}
}
-/* This is necessary so that this server can know where to put its
- tickets. */
-char *tkt_string()
-{
- return("/tmp/tkt_ureg");
-}
-
int parse_encrypted(message,data)
struct msg *message; /* Formatted packet */
- struct db_data *data; /* Data from the SMS database */
+ struct db_data *data; /* Data from the Moira database */
/* This routine makes sure that the ID from the database matches
the ID sent accross in the packet. The information in the packet
was created in the following way:
The plain text ID number was encrypted via EncryptID() resulting
- in the form that would appear in the SMS database. This is
+ in the form that would appear in the Moira database. This is
concatinated to the plain text ID so that the ID string contains plain
text ID followed by a null followed by the encrypted ID. Other
information such as the username or password is appended. The whole
zero and initializes all the fields of the formatted packet structure
that depend on the encrypted information. */
{
- C_Block key; /* The key for DES en/decryption */
- Key_schedule sched; /* En/decryption schedule */
+ des_cblock key; /* The key for DES en/decryption */
+ des_key_schedule sched; /* En/decryption schedule */
static char decrypt[BUFSIZ]; /* Buffer to hold decrypted information */
long decrypt_len; /* Length of decypted ID information */
char recrypt[14]; /* Buffer to hold re-encrypted information */
int status = SUCCESS; /* Error status */
#ifdef DEBUG
- com_err(whoami,0,"Entering parse_encrypted");
+ com_err(whoami, 0, "Entering parse_encrypted");
#endif
/* Make the decrypted information length the same as the encrypted
because of the DES encryption routines. */
decrypt_len = (long)message->encrypted_len;
- /* Get key from the one-way encrypted ID in the SMS database */
- string_to_key(data->mit_id, key);
+ /* Get key from the one-way encrypted ID in the Moira database */
+ des_string_to_key(data->mit_id, key);
/* Get schedule from key */
- key_sched(key, sched);
+ des_key_sched(key, sched);
/* Decrypt information from packet using this key. Since decrypt_len
is an integral multiple of eight bytes, it will probably be null-
padded. */
- pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, DECRYPT);
+ des_pcbc_encrypt(message->encrypted, decrypt, decrypt_len,
+ sched, key, DES_DECRYPT);
/* Extract the plain text and encrypted ID fields from the decrypted
packet information. */
message->leftover = temp;
message->leftover_len = len;
/* Since we know we have the right user, fill in the information
- from the SMS database. */
+ from the Moira database. */
message->db.reg_status = data->reg_status;
(void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid));
(void) strncpy(message->db.mit_id,data->mit_id,
#ifdef DEBUG
if (status)
- com_err(whoami,status," parse_encrypted failed.");
+ com_err(whoami, status, " in parse_encrypted");
else
- com_err(whoami,status,"parse_encrypted succeeded.");
+ com_err(whoami, status, "parse_encrypted succeeded");
#endif
return status;
}
int db_callproc(argc,argv,queue)
- int argc; /* Number of arguments returned by SMS */
- char *argv[]; /* Arguments returned by SMS */
+ int argc; /* Number of arguments returned by Moira */
+ char *argv[]; /* Arguments returned by Moira */
struct save_queue *queue; /* Queue to save information in */
/* This function is called by sms_query after each tuple found. It is
used by find_user to cache information about each user found. */
int status = SUCCESS; /* Error status */
#ifdef DEBUG
- com_err(whoami,0,"Entering db_callproc.");
+ com_err(whoami, 0, "Entering db_callproc.");
#endif
if (argc != U_END)
}
else
{
- /* extract the needed information from the results of the SMS query */
+ /* extract the needed information from the results of the Moira query */
data = (struct db_data *)malloc(sizeof(struct db_data));
data->reg_status = atoi(argv[U_STATE]);
(void) strncpy(data->login,argv[U_NAME],sizeof(data->login));
int find_user(message)
struct msg *message; /* Formatted packet structure */
/* This routine verifies that a user is allowed to register by finding
- him/her in the SMS database. It returns the status of the SMS
+ him/her in the Moira database. It returns the status of the Moira
query that it calls. */
{
#define GUBN_ARGS 2 /* Arguements needed by get_user_by_name */
char *q_argv[GUBN_ARGS]; /* Arguments to query */
int status = SUCCESS; /* Query return status */
- struct save_queue *queue; /* Queue to hold SMS data */
+ struct save_queue *queue; /* Queue to hold Moira data */
struct db_data *data; /* Structure for data for one tuple */
short verified = FALSE; /* Have we verified the user? */
if (status == SUCCESS)
{
- /* Get ready to make an SMS query */
+ /* Get ready to make an Moira query */
q_name = "get_user_by_name";
q_argc = GUBN_ARGS; /* #defined in this routine */
q_argv[0] = message->first;
int status = SUCCESS; /* Return status */
/* Log that we are about to veryify user */
- com_err(whoami,0,"verify_user %s %s",message->first,message->last);
+ com_err(whoami, 0, "verifying user %s %s",message->first,message->last);
/* Figure out what user (if any) can be found based on the
encrypted information in the packet. (See the comment on
status = find_user(message);
- /* If SMS coudn't find the user */
+ /* If Moira coudn't find the user */
if (status == SMS_NO_MATCH)
status = UREG_USER_NOT_FOUND;
else if (status == SMS_SUCCESS)
case US_NOT_ALLOWED:
status = UREG_NOT_ALLOWED;
break;
-
+ case US_ENROLLED:
+ status = UREG_ENROLLED;
+ break;
+ case US_ENROLL_NOT_ALLOWED:
+ status = UREG_ENROLL_NOT_ALLOWED;
+ break;
+ case US_HALF_ENROLLED:
+ status = UREG_HALF_ENROLLED;
+ break;
default:
status = UREG_MISC_ERROR;
- critical_alert(FAIL_INST,"Bad user state for login %s.",
- message->db.login);
+ critical_alert(FAIL_INST,"Bad user state %d for login %s.",
+ message->db.reg_status, message->db.login);
break;
}
/* Set retval to the login name so that the client can use
}
}
- com_err(whoami,status," returned from verify_user");
+ if (status)
+ com_err(whoami, status, " returned from verify_user");
+ else
+ com_err(whoami, 0, "User verified");
return status;
}
-int ureg_get_tkt()
+int ureg_kadm_init()
{
- int status = SUCCESS; /* Return status */
+ unsigned int status = SUCCESS; /* Return status */
+ static char krbrealm[REALM_SZ]; /* kerberos realm name */
+ static char hostbuf[BUFSIZ], *host; /* local hostname in principal fmt */
+ static int inited = 0;
+ char *p;
+
+#ifdef DEBUG
+ com_err(whoami, 0, "Entering ureg_kadm_init");
+#endif DEBUG
+
+ if (!inited) {
+ inited++;
+ bzero(krbrealm, sizeof(krbrealm));
+ if (status = krb_get_lrealm(krbrealm, 1)) {
+ status += krb_err_base;
+ com_err(whoami, status, " fetching kerberos realm");
+ exit(1);
+ }
+ if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
+ com_err(whoami, errno, "getting local hostname");
+ host = canonicalize_hostname(strsave(hostbuf));
+ for (p = host; *p && *p != '.'; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+ *p = 0;
+ }
/* Get keys for interacting with Kerberos admin server. */
/* principal, instance, realm, service, service instance, life, file */
- if (status = get_svc_in_tkt("register", "sms", krbrealm, "changepw",
- krbhst, 1, KEYFILE))
+ if (status = krb_get_svc_in_tkt(MOIRA_SNAME, host, krbrealm, PWSERV_NAME,
+ KADM_SINST, 1, KEYFILE))
status += krb_err_base;
-
+
+ if (status != SUCCESS)
+ com_err(whoami, status, " while get admin tickets");
#ifdef DEBUG
- if (status == SUCCESS)
- com_err(whoami,status,"Succeeded in getting tickets.");
- else
- com_err(whoami,status,"Failed to get tickets.");
+ else {
+ com_err(whoami, status, "Succeeded in getting admin tickets");
+ }
#endif
+
+ if (status == SUCCESS) {
+ if ((status = kadm_init_link(PWSERV_NAME, KADM_SINST, krbrealm)) !=
+ KADM_SUCCESS) {
+ com_err(whoami, status, " while initializing kadmin connection");
+ }
+ }
+
return status;
}
return FAILURE;
}
-int do_admin_call(login, passwd, uid)
- char *login; /* Requested kerberos principal */
- char *passwd; /* Requested password */
- char *uid; /* Uid of user who owns this principal */
- /* This routine gets tickets, makes the appropriate call to admin_call,
- and destroys tickets. */
+/*
+ * This routine reserves a principal in kerberos by setting up a
+ * principal with a random initial key.
+ */
+int reserve_krb(login)
+ char *login;
{
- int status; /* Error status */
- char uid_buf[20]; /* Holds uid for kerberos */
+ int status = SUCCESS;
+ Kadm_vals new;
+ des_cblock key;
+ u_long *lkey = (u_long *)key;
- com_err(whoami,0,"Entering do_admin_call");
+#ifdef DEBUG
+ com_err(whoami, 0, "Entering reserve_krb");
+#endif DEBUG
- if ((status = ureg_get_tkt()) == SUCCESS)
- {
- /* Try to reserve kerberos principal. To do this, send a
- password request and a null password. It will only succeed
- if there is no principal or the principal exists and has no
- password. */
- /* 13 chars of placebo for backwards-compatability - the admin
- server protocol reqires this. */
- bzero(uid_buf,sizeof(uid_buf));
- (void) sprintf(uid_buf, "%13s", uid);
+ if ((status = ureg_kadm_init()) == SUCCESS) {
+ bzero((char *)&new, sizeof(new));
+ SET_FIELD(KADM_DESKEY, new.fields);
+ SET_FIELD(KADM_NAME, new.fields);
- if ((status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, login,
- "", passwd, uid_buf)) != KSUCCESS)
- {
- com_err(whoami,status," server error: %s",admin_errmsg);
-
- if (strcmp(admin_errmsg,
- "Principal already in kerberos database.") == 0)
- status = UREG_KRB_TAKEN;
- critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.",
- login);
+ (void) des_random_key(key);
+ new.key_low = htonl(lkey[0]);
+ new.key_high = htonl(lkey[1]);
+ strcpy(new.name, login);
+
+ com_err(whoami, 0, "Creating kerberos principal for %s", login);
+ status = kadm_add(&new);
+ if (status != KADM_SUCCESS)
+ com_err(whoami, status, " while reserving principal");
+
+ bzero((char *)&new, sizeof(new));
+ }
+
+ dest_tkt();
+
+ return(status);
+}
+
+/*
+ * This routine reserves a principal in kerberos by setting up a
+ * principal with a random initial key.
+ */
+int setpass_krb(login, password)
+ char *login;
+ char *password;
+{
+ int status = SUCCESS;
+ Kadm_vals new;
+ des_cblock key;
+ u_long *lkey = (u_long *)key;
+
+ if ((status = ureg_kadm_init()) == SUCCESS) {
+ bzero((char *)&new, sizeof(new));
+ SET_FIELD(KADM_DESKEY, new.fields);
+ SET_FIELD(KADM_NAME, new.fields);
+
+ (void) des_string_to_key(password, key);
+ new.key_low = htonl(lkey[0]);
+ new.key_high = htonl(lkey[1]);
+ strcpy(new.name, login);
+
+ com_err(whoami, 0, "Setting password for %s", login);
+ /* First arguement is not used if user has modify privileges */
+ if ((status = kadm_mod(&new, &new)) != KADM_SUCCESS) {
+ if (status == KADM_NOENTRY) {
+ com_err(whoami, 0,
+ "kerberos principal doesn't exist; creating");
+ if ((status = kadm_add(&new)) != KADM_SUCCESS)
+ com_err(whoami, status,
+ " while creating kerberos principal");
+ }
+ else
+ com_err(whoami, status, " while setting password");
}
}
dest_tkt();
- com_err(whoami,status," returned from do_adin_call");
- return status;
+ return(status);
}
int reserve_user(message,retval)
char *retval;
{
int q_argc; /* Number of arguments to query */
- char *q_argv[3]; /* Arguments to SMS query */
- char *q_name; /* Name of SMS query */
+ char *q_argv[3]; /* Arguments to Moira query */
+ char *q_name; /* Name of Moira query */
int status = SUCCESS; /* General purpose error status */
char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
char *login; /* The login name the user wants */
register int i; /* A counter */
/* Log that we are about to reserve a user. */
- com_err(whoami, 0, "reserve_user %s %s",
+ com_err(whoami, 0, "reserving user %s %s",
message->first, message->last);
/* Check to make sure that we can verify this user. */
login = message->leftover;
/* Check the login name for validity. The login name is currently
- is allowed to contain lowercase letters and numbers in any
- position and underscore characters and periods in any position
- but the first. */
+ is allowed to contain lowercase letters in any position and
+ and numbers and underscore characters in any position but the
+ first. */
if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
status = UREG_INVALID_UNAME;
}
if (status == SUCCESS)
- if ((login[0] == '.') || (login[1] == '_'))
+ if ((login[0] == '_') || isdigit(login[0]))
status = UREG_INVALID_UNAME;
+
if (status == SUCCESS)
{
for (i = 0; i < strlen(login); i++)
- if (!islower(login[i]) && !isdigit(login[i]) &&
- (login[i] != '_') && (login[i] != '.'))
+ if (!islower(login[i]) && !isdigit(login[i]) &&
+ (login[i] != '_'))
{
status = UREG_INVALID_UNAME;
break;
{
/* Now that we have a valid user with a valid login... */
- /* First, try to reserve the user in SMS. */
+ /* First, try to reserve the user in Moira. */
(void) sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
q_name = "register_user";
q_argv[0] = message->db.uid;
case SMS_IN_USE:
status = UREG_LOGIN_USED;
break;
- default:
+ case SMS_DEADLOCK:
status = UREG_MISC_ERROR;
+ break;
+ default:
critical_alert(FAIL_INST,"%s returned from register_user.",
error_message(status));
+ status = UREG_MISC_ERROR;
break;
}
}
+
if (status == SUCCESS)
{
- /* SMS login was successfully created; try to reserve kerberos
- principal. */
- /* If this routine fails, store the login in the retval so
- that it can be used in the client-side error message. */
- if ((status = do_admin_call(login, "", message->db.uid)) != SUCCESS)
+ /*
+ * Moira login was successfully created; try to reserve kerberos
+ * principal.
+ *
+ * If this routine fails, store the login in the retval so
+ * that it can be used in the client-side error message.
+ */
+ if ((status = reserve_krb(login)) != SUCCESS)
(void) strcpy(retval, login);
}
- com_err(whoami, status, " returned from reserve_user");
+ if (status)
+ com_err(whoami, status, " returned from reserve_user");
+ else {
+ com_err(whoami, 0, "User reserved");
+ }
return status;
}
-int set_final_status(login)
- char *login;
+int set_final_status(message)
+struct msg *message;
/* This routine updates a user's registration status to fully
registered. */
{
- char *q_name; /* Name of SMS query */
- int q_argc; /* Number of arguments for SMS query */
+ char *login;
+ char *q_name; /* Name of Moira query */
+ int q_argc; /* Number of arguments for Moira query */
char *q_argv[2]; /* Arguments to get user by uid */
char state[7]; /* Can hold a 16 bit integer */
int status; /* Error status */
- com_err(whoami, 0, "Setting final status for %s", login);
+ if (message->request == UREG_SET_PASSWORD)
+ (void) sprintf(state,"%d",US_REGISTERED);
+ else if (message->db.reg_status == US_NO_LOGIN_YET)
+ (void) sprintf(state,"%d",US_ENROLLED);
+ else
+ (void) sprintf(state,"%d",US_ENROLL_NOT_ALLOWED);
+
+ login = message->db.login;
+ com_err(whoami, 0, "Setting final status for %s to %s", login, state);
- (void) sprintf(state,"%d",US_REGISTERED);
q_name = "update_user_status";
q_argc = 2;
q_argv[0] = login;
q_argv[1] = state;
if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
- (char *)0)) != SMS_SUCCESS)
- critical_alert(FAIL_INST,"%s returned from update_user_status.",
- error_message(status));
-
- com_err(whoami,status," returned from set_final_status");
+ (char *)0)) != SMS_SUCCESS) {
+ if (status == SMS_DEADLOCK)
+ status = UREG_MISC_ERROR;
+ else
+ critical_alert(FAIL_INST,"%s returned from update_user_status.",
+ error_message(status));
+ }
+ if (status)
+ com_err(whoami, status, " returned from set_final_status");
+ else
+ com_err(whoami, 0, "Final status set");
return status;
}
int status = SUCCESS; /* Return status */
char *passwd; /* User's password */
- com_err(whoami, 0, " set_password %s %s",
+ com_err(whoami, 0, "setting password %s %s",
message->first, message->last);
status = verify_user(message,retval);
is that he exists and has no password. */
if (status == SUCCESS)
status = UREG_NO_LOGIN_YET;
- if (status == UREG_NO_PASSWD_YET)
+ if (((int)message->request == UREG_SET_PASSWORD &&
+ status == UREG_NO_PASSWD_YET) ||
+ ((int)message->request == UREG_GET_KRB &&
+ status == UREG_HALF_ENROLLED))
{
/* User is in proper state for this transaction. */
passwd = message->leftover;
/* Set password. */
- if ((status = do_admin_call(message->db.login,
- passwd, message->db.uid)) != SUCCESS)
+ if ((status = setpass_krb(message->db.login, passwd)) != SUCCESS)
/* If failure, allow login name to be used in client
error message */
(void) strcpy(retval,message->db.login);
else
/* Otherwise, mark user as finished. */
- status = set_final_status(message->db.login);
+ status = set_final_status(message);
}
- com_err(whoami, status, " returned from set_passwd");
-
+
+ if (status)
+ com_err(whoami, status, " returned from set_passwd");
+ else
+ com_err(whoami, 0, "Password set");
+
return status;
}
+
+
+int getuserinfo(argc, argv, qargv)
+int argc;
+char **argv;
+char **qargv;
+{
+ int status = SUCCESS;
+
+ if (argc != U_END) {
+ critical_alert(FAIL_INST,
+ "Wrong number of args returned from get_user_by_uid");
+ status = SMS_ABORT;
+ } else {
+ qargv[U_NAME] = strsave(argv[U_NAME]);
+ qargv[U_UID+1] = strsave(argv[U_UID]);
+ qargv[U_SHELL+1] = strsave(argv[U_SHELL]);
+ qargv[U_LAST+1] = strsave(argv[U_LAST]);
+ qargv[U_FIRST+1] = strsave(argv[U_FIRST]);
+ qargv[U_MIDDLE+1] = strsave(argv[U_MIDDLE]);
+ qargv[U_STATE+1] = strsave(argv[U_STATE]);
+ qargv[U_MITID+1] = strsave(argv[U_MITID]);
+ qargv[U_CLASS+1] = strsave(argv[U_CLASS]);
+ qargv[U_MODTIME+1] = NULL;
+ }
+ return(status);
+}
+
+
+int set_identity(message,retval)
+struct msg *message;
+char *retval;
+{
+ int q_argc; /* Number of arguments to query */
+ char *q_argv[U_END]; /* Arguments to Moira query */
+ char *q_name; /* Name of Moira query */
+ int status = SUCCESS; /* General purpose error status */
+ char fstype_buf[7]; /* Buffer to hold fs_type, a 16 bit number */
+ char *login; /* The login name the user wants */
+ register int i; /* A counter */
+
+ /* Log that we are about to reserve a user. */
+ com_err(whoami, 0, "setting identity %s %s",
+ message->first, message->last);
-/*
- * Local Variables:
- * mode: c
- * c-argdecl-indent: 2
- * c-brace-offset: -4
- * c-continued-statement-offset: 4
- * c-indent-level: 4
- * c-label-offset: -2
- * End:
- */
+ /* Check to make sure that we can verify this user. */
+ status = verify_user(message,retval);
+ if (status == SUCCESS || status == UREG_NOT_ALLOWED)
+ {
+ status = SUCCESS;
+ /* Get the requested login name from leftover packet information. */
+ login = message->leftover;
+
+ /* Check the login name for validity. The login name is currently
+ is allowed to contain lowercase letters in any position and
+ and numbers and underscore characters in any position but the
+ first. */
+ if ((strlen(login) < MIN_UNAME) || (strlen(login) > MAX_UNAME))
+ status = UREG_INVALID_UNAME;
+ }
+ if (status == SUCCESS)
+ if ((login[0] == '_') || isdigit(login[0]))
+ status = UREG_INVALID_UNAME;
+ if (status == SUCCESS)
+ {
+ for (i = 0; i < strlen(login); i++)
+ if (!islower(login[i]) && !isdigit(login[i]) &&
+ (login[i] != '_'))
+ {
+ status = UREG_INVALID_UNAME;
+ break;
+ }
+ }
+ if (status == SUCCESS)
+ {
+ /* Now that we have a valid user with a valid login... */
+
+ q_argv[0] = message->db.uid;
+ status = sms_query("get_user_by_uid", 1, q_argv, getuserinfo, q_argv);
+ if (status != SUCCESS) {
+ com_err(whoami, status, " while getting user info");
+ return(status);
+ }
+ q_argv[U_NAME+1] = login;
+ q_argv[U_STATE+1] = "7";
+ status = sms_query("update_user", U_MODTIME+1, q_argv,
+ null_callproc, NULL);
+ switch (status)
+ {
+ case SMS_SUCCESS:
+ status = SUCCESS;
+ break;
+ case SMS_IN_USE:
+ status = UREG_LOGIN_USED;
+ break;
+ case SMS_DEADLOCK:
+ status = UREG_MISC_ERROR;
+ break;
+ default:
+ critical_alert(FAIL_INST,"%s returned from update_user.",
+ error_message(status));
+ status = UREG_MISC_ERROR;
+ break;
+ }
+ }
+ if (status == SUCCESS)
+ {
+ /* Moira login was successfully created; try to reserve kerberos
+ principal. */
+ /* If this routine fails, store the login in the retval so
+ that it can be used in the client-side error message. */
+ if ((status = reserve_krb(login)) != SUCCESS)
+ (void) strcpy(retval, login);
+ }
+
+ if (status)
+ com_err(whoami, status, " returned from set_identity");
+ else
+ com_err(whoami, 0, "Identity set");
+
+ return status;
+}
+
+
+void reg_com_err_hook(whoami, code, fmt, pvar)
+ char *whoami;
+ int code;
+ char *fmt;
+ caddr_t pvar;
+{
+ if (whoami) {
+ fputs(whoami, stderr);
+ fputs(": ", stderr);
+ }
+ if (code) {
+ fputs(error_message(code), stderr);
+ }
+ if (fmt) {
+ _doprnt(fmt, pvar, stderr);
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+}