]> andersk Git - moira.git/blobdiff - reg_svr/reg_svr.c
Send zgrams if the disk usage is over 90% or the quota change, if used, would bring...
[moira.git] / reg_svr / reg_svr.c
index 95a29d604c3b582f330fd7018880df45545f0038..60dd1006241068c2051b3a8eaa6c035c87f9e1c1 100644 (file)
  *      $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 SMS server and the Kerberos
- *      admin_server, and is a server for the userreg program.
- * 
- *      $Log$
- *      Revision 1.10  1988-08-01 18:17:58  qjb
- *      Almost finished version supporting new SMS protocol.
- *      Kerberos problems.
- *
- * Revision 1.9  88/07/26  14:50:40  qjb
- * Added comments and did some cleaning up in preparation for rewrite.
- * This version will not run; the last version that will is 1.8.
- * 
- * Revision 1.8  88/07/20  15:39:25  mar
- * find realm at runtime; don't use hard-coded one
- * 
- * Revision 1.7  88/02/08  15:08:15  mar
- * Moved header file locations
- * 
- * Revision 1.6  87/09/21  15:19:11  wesommer
- * Allow numbers, _, and . as legal characters in the username.
- * 
- * Revision 1.5  87/09/10  22:18:32  wesommer
- * Clean up output format.
- * 
- * Revision 1.4  87/09/04  23:33:19  wesommer
- * Deleted test scaffolding (second oops.)
- * 
- * Revision 1.3  87/09/03  03:05:18  wesommer
- * Version used for userreg tests.
- * 
- * Revision 1.2  87/08/22  18:39:45  wesommer
- * User registration server.
- * 
- * Revision 1.1  87/07/31  15:48:13  wesommer
- * Initial revision
- * 
+ *      This program is a client of the Kerberos admin_server and a
+ *      server for the userreg program.  It is not a client of the
+ *      Moira server as it is linked with libmoiraglue which bypasses
+ *      the network protocol.
  */
 
 #ifndef lint
 static char *rcsid_reg_svr_c = "$Header$";
 #endif lint
 
+#include <mit-copyright.h>
 #include <stdio.h>
 #include <strings.h>
 #include <ctype.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/file.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
 #include <krb.h>
 #include <des.h>
+#include <kadm.h>
+#include <kadm_err.h>
+#include <krb_err.h>
 #include <errno.h>
-#include <ctype.h>
-#include "ureg_err.h"
-#include "ureg_proto.h"
-#include "sms.h"
-#include "sms_app.h"
-#include "admin_server.h"
-#include "admin_err.h"
-
-#define CUR_UREG_VERSION 1     /* Version for the register protocol */
-#define SUCCESS 0              /* General purpose success code */
-#define NON_ZERO 1             /* To use when any non-zero number will work */
-#define min(a,b) ((a)>(b)?(b):(a))
-#define CRYPT_LEN 14           /* crypt() returns a 13 char string */
-#define LOGIN_LEN 9            /* Maximum 8 character login name */
-#define UID_LEN 7              /* Allow room for a 16 bit number */
-
-#define DEBUG
-
-extern int abort();
-extern char *strdup();
-extern char *malloc();
-extern int krb_err_base;
-extern char admin_errmsg[];
+#include "moira.h"
+#include "moira_site.h"
+#include "reg_svr.h"
 
-extern char *whoami;           /* Name of program */
-extern int errno;              /* Unix error number */
-
-/* Global variables */
-char tmpbuf[BUFSIZ];           /* A general purpose temporary buffer */
+extern char admin_errmsg[];
 
-/* This structure holds information from the SMS database that will be
-   worth holding on to.  An instance of it appears in the formatted 
-   packet structure. */
-struct db_data
-{
-    char mit_id[CRYPT_LEN];    /* Encrypted MIT ID */
-    int reg_status;            /* Registration status */
-    char uid[UID_LEN];         /* Reserved uid */
-    char login[LOGIN_LEN];     /* Login (username) */
-};
-
-/* This structure stores information sent over in the packet and also
-   some information obtained from the database that will be needed 
-   for each transaction. */
-struct msg                     /* Holds processed packet information */
-{    
-    u_long version;            /* Userreg version */
-    u_long request;            /* Request */
-    char *first;               /* First name */
-    char *last;                        /* Last name */
-    char *encrypted;           /* Encrypted information in packet */
-    int encrypted_len;         /* Length of encrypted information in packet */
-    char *leftover;            /* Leftover information sent in the packet */
-    int leftover_len;          /* Length of leftover information */
-    struct db_data db;         /* Information from the SMS database */
-};
+void reg_com_err_hook();
 
 main(argc,argv)
   int argc;
   char *argv[];
 {
-    struct servent *sp;                /* Service info from /etc/services */
-    int s;                     /* Socket descriptor */
-    struct sockaddr_in sin;    /* Internet style socket address */
-    int addrlen;               /* Size of socket address (sin) */
-    char packet[BUFSIZ];       /* Buffer for packet transmission */
-    int pktlen;                        /* Size of packet */
-    u_long seqno;              /* Sequence number for packet transmission */
     struct msg message;                /* Storage for parsed packet */
-    int status = 0;            /* General purpose error status */
+    int status = SUCCESS;      /* Error status */
     char retval[BUFSIZ];       /* Buffer to hold return message for client */
     
-    int parse_pkt();           /* Parse a packet from the client */
-    void format_pkt();         /* Prepare a packet to send to client*/
-    int verify_user();         /* Makes sure user is allowed to register */
-    int reserve_user();                /* Reserve a login for this user */
-    int set_password();                /* Set this user's password */
+    void req_initialize();     /* Initialize request layer */
+    void get_request();                /* Get a request */
+    void report();             /* Respond to a request */
 
+    /* Initialize */
     whoami = argv[0];
-
+    
     /* 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 */
+    /* Initialize com_err error tables */
     init_ureg_err_tbl();
+    init_krb_err_tbl();
+    init_kadm_err_tbl();
+    initialize_gdss_error_table();
     
-    /* Get service information from /etc/services */
-    if ((sp = getservbyname("sms_ureg", "udp")) == NULL) 
-    {
-       fprintf(stderr, "Unknown service sms_ureg/udp\n");
-       exit(1);
-    }
+    /* Use com_err or output to stderr for all log messages. */    
+#ifdef DEBUG
+    com_err(whoami, 0, "*** Debugging messages enabled. ***");
+#endif DEBUG
     
-    /* Get an internet style datagram socket */
-    if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) 
+    /* Set the name of our kerberos ticket file */
+    krb_set_tkt_string("/tmp/tkt_ureg");
+
+    /* Connect to the Moira server */
+    if ((status = mr_connect(MOIRA_SERVER)) != MR_SUCCESS) 
     {
-       com_err(whoami,errno,"socket");
+       com_err(whoami, status, " on mr_connect");
        exit(1);
     }
-    bzero((char *)&sin,(int)sizeof(sin));
-    
-    sin.sin_family = AF_INET;
-    sin.sin_port = sp->s_port;
-    sin.sin_addr.s_addr = INADDR_ANY;
     
-    /* Bind a name to the socket */
-    if (bind(s, &sin, sizeof(sin)) < 0
+    /* Authorize, telling the server who you are */
+    if ((status = mr_auth(whoami)) != MR_SUCCESS
     {
-       com_err(whoami,errno,"bind");
+       com_err(whoami, status, " on mr_auth");
        exit(1);
     }
     
-    /* Connect to the SMS server */
-    if ((status = sms_connect()) != SMS_SUCCESS) 
-    {
-       com_err(whoami, status, " on connect");
+    journal = fopen(REGJOURNAL, "a");
+    if (journal == NULL) {
+       com_err(whoami, errno, " while opening journal file");
        exit(1);
     }
     
-    /* Authorize, telling the server who you are */
-    if ((status = sms_auth(whoami)) != SMS_SUCCESS) 
-    {
-       com_err(whoami, status, " on auth");
-       exit(1);
-    }
+    /* Allow request layer to initialize */
+    req_initialize();
     
-#ifdef DEBUG
-    fprintf(stderr,"*** Debugging messages enabled. ***\n");
-#endif DEBUG
-
     /* Sit around waiting for requests from the client. */
     for (;;) 
     {
-       com_err(whoami, 0, "*** Ready for next request ***");
-       addrlen = sizeof(sin);
-       bzero(retval, BUFSIZ);
-       /* Receive a packet into buf. */
-       if ((pktlen = recvfrom(s,packet,sizeof(packet),0,&sin,&addrlen)) < 0) 
-       {
-           com_err(whoami,errno,"recvfrom");
-           if (errno == EINTR) continue;
-           exit(1);
-       }
-       
-       /* Parse a request packet */
-       if ((status = parse_pkt(packet, pktlen, &seqno, &message)) != 0) 
-       {
-           pktlen = sizeof(packet);
-           /* Format packet to send back to the client */
-           format_pkt(packet, &pktlen, seqno, status, (char *)NULL);
-           /* Report the error the the client */
-           (void) sendto(s, packet, pktlen, 0, &sin, addrlen);
-           continue;
-       }
+       get_request(&message);
        
-       /* do action */
        switch((int)message.request) 
        {
          case UREG_VERIFY_USER:
@@ -225,87 +111,57 @@ main(argc,argv)
            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;
+         case UREG_GET_SECURE:
+           status = get_secure(&message,retval);
+           break;
+         case UREG_SET_SECURE:
+           status = set_secure(&message,retval);
+           break;
          default:
            status = UREG_UNKNOWN_REQUEST;
+           critical_alert(FAIL_INST,"Unknown request %d from userreg.",
+                          message.request);
            break;
        }
        
        /* Report what happened to client */
-       pktlen = sizeof(packet);
-       format_pkt(packet, &pktlen, seqno, status, retval);
-       sendto(s, packet, pktlen, 0, &sin, addrlen);
+       report(status, retval);
     }
 }
 
-void format_pkt(packet, pktlenp, seqno, status, message)
-  char *packet;
-  int *pktlenp;
-  u_long seqno;
-  int status;
-  char *message;
-  /* This routine prepares a packet to send back to the client. */
-{
-    u_long vers = htonl((u_long)CUR_UREG_VERSION);
-    status = htonl((u_long)status);
-    
-    /* Put current SMS version into the packet */
-    bcopy((char *)&vers, packet, sizeof(long));
-    /* Put sequence number into the packet */
-    bcopy((char *)&seqno, packet+sizeof(long), sizeof(long));
-    /* Put error status into the packet */
-    bcopy((char *)&status, packet+ 2*sizeof(long), sizeof(long));
-    *pktlenp = sizeof(long) * 3;
-    /* Copy the message into the packet */
-    (void) strcpy(packet+3*sizeof(long), message);
-    (*pktlenp) += strlen(message);
-}
-
-encrypt_mitid(encrypt, idnumber, first, last)
-  char *encrypt;               /* Buffer to hold newly encrypted  */
-  char *idnumber;              /* Plain text ID */
-  char *first;                 /* First name */
-  char *last;                  /* Last name */
-/* A routine with exactly this function belongs in the SMS library. ### 
-   This routine encrypts the MIT ID so that it will match what is in the
-   database. */
-{
-    char salt[3];
-    extern char *crypt();
-    
-    /* Use the last and first initials as salt. */
-    salt[0] = tolower(last[0]);
-    salt[1] = tolower(first[0]);
-    salt[2] = 0;
-
-    (void) strcpy(encrypt, crypt(&idnumber[2], salt));
-}
-
 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 crypt() resulting in
-   the form that would appear in the SMS 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 are appended.
-   The whole thing is then DES encrypted using the encrypted ID as 
-   the source of the key.
+   The database used to contain encrypted IDs.  Now we don't encrypt
+   them in the database, although there are still some encrypted IDs
+   there.
+
+   The plain text ID number was encrypted via EncryptID() resulting
+   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
+   thing is then DES encrypted using the encrypted ID as the source of
+   the key.
 
-   This routine tries each encrypted ID in the database that belongs
+   This routine tries each ID in the database that belongs
    to someone with this user's first and last name and tries to 
    decrypt the packet with this information.  If it succeeds, it returns 
-   zero and initialize all the fields of message that depend on the
-   information encrypted. */
+   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 */
@@ -313,10 +169,10 @@ int parse_encrypted(message,data)
     char idnumber[BUFSIZ];     /* Buffer to hold plain-text ID */
     char *temp;                        /* A temporary string pointer */
     int len;                   /* Keeps track of length left in packet */
-    int status = 0;            /* Error status */
+    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
@@ -324,19 +180,23 @@ int parse_encrypted(message,data)
        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 possibly one-way encrypted ID in the Moira database */
+    if (data->mit_id[0] >= '0' && data->mit_id[0] <= '9') {
+       char buf[32];
+
+       EncryptID(buf, data->mit_id, message->first, message->last);
+       des_string_to_key(buf, key);
+    } else
+      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);
     
-#ifdef DEBUG
-    fprintf(stderr,"Decrypted information: %s\n",decrypt);
-#endif
-
     /* Extract the plain text and encrypted ID fields from the decrypted
        packet information. */
     /* Since the decrypted information starts with the plain-text ID
@@ -345,85 +205,88 @@ int parse_encrypted(message,data)
        important that strncpy be used because if we are not using the
        correct key, there is no guarantee that a null will occur
        anywhere in the string. */
-    (void)strncpy(idnumber,decrypt,(int)decrypt_len);
+    (void) strncpy(idnumber,decrypt,(int)decrypt_len);
+    /* Check that the idnumber of a mismatched decryption doesn't overflow
+     * the buffer.
+     */
+    if (strlen(idnumber) != 9) {
+#ifdef DEBUG
+       com_err(whoami, 0, "idnumber wrong size, probable user mismatch\n");
+#endif
+       return(FAILURE);
+    }
     /* Point temp to the end of the plain text ID number. */
     temp = decrypt + strlen(idnumber) + 1;
-    /* Find out how much more room there is. */
+    /* Find out how much more packet there is. */
     len = message->encrypted_len - (temp - decrypt);
-    /* Copy the next 14 bytes of the decrypted information into 
-       hashid if there are 14 more bytes to copy.  There will be
+    /* Copy the next CRYPT_LEN bytes of the decrypted information into 
+       hashid if there are CRYPT_LEN more bytes to copy.  There will be
        if we have the right key. */
-    (void) strncpy(hashid, temp, min(len, 14));
+    (void) strncpy(hashid, temp, min(len, CRYPT_LEN));
     /* Point temp to the end of the encrypted ID field */
     temp += strlen(hashid) + 1;
     /* Find out how much more room there is. */
     len = message->encrypted_len - (temp - decrypt);
     
-    /* Now compare encrypted ID's don't match. */
-    if (strcmp(hashid, data->mit_id)) status = NON_ZERO;
-    if (!status)
-    {
-       encrypt_mitid(recrypt, idnumber, message->first, message->last);
-       /* Now compare encrypted plain text to ID from database. */
-       if (strcmp(recrypt, data->mit_id)) status = NON_ZERO;
-    }
+    /* Now compare encrypted ID and clear text ID for a match. */
+    if (strcmp(hashid, data->mit_id) &&
+       strcmp(idnumber, data->mit_id))
+      status = FAILURE;
     
-    if (!status)
+    if (status == SUCCESS)
     {
        /* We made it.  Now we can finish initializing message. */
        /* Point leftover to whatever is left over! */
        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;
-       strncpy(message->db.uid,data->uid,
-               sizeof(message->db.uid));
-       strncpy(message->db.mit_id,data->mit_id,
-               sizeof(message->db.mit_id));
-       strncpy(message->db.login,data->login,
-               sizeof(message->db.login));
+       (void) strncpy(message->db.uid,data->uid, sizeof(message->db.uid));
+       (void) strncpy(message->db.mit_id,data->mit_id, 
+                      sizeof(message->db.mit_id));
+       (void) strncpy(message->db.login,data->login, sizeof(message->db.login));
     }
     
 #ifdef DEBUG
     if (status)
-       com_err(whoami,0,"parse_encrypted failed.");
+       com_err(whoami, status, " in parse_encrypted");
     else
-       com_err(whoami,0,"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.  This
-   routine has knowledge of the format of the query result built into
-   it.  This must change. ### */
+/* This function is called by mr_query after each tuple found.  It is
+   used by find_user to cache information about each user found.  */
 {
     struct db_data *data;      /* Structure to store the information in */
-    int status = 0;            /* Error status */
+    int status = SUCCESS;      /* Error status */
     
 #ifdef DEBUG
-    com_err(whoami,0,"Entering db_callproc.");
+    com_err(whoami, 0, "Entering db_callproc.");
 #endif
 
-    if (argc != 12)
+    if (argc != U_END)
     {
-       /* Wrong number of arguments; stop searching and send email ### */
-       status = NON_ZERO;
+       critical_alert
+           (FAIL_INST,
+            "Wrong number of arguments returned from get_user_account_by_name.");
+       status = MR_ABORT;
     }
     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[6]);
-       strncpy(data->login,argv[0],sizeof(data->login));
-       strncpy(data->mit_id,argv[7],sizeof(data->mit_id));
-       strncpy(data->uid,argv[1],sizeof(data->uid));
+       data->reg_status = atoi(argv[U_STATE]);
+       (void) strncpy(data->login,argv[U_NAME],sizeof(data->login));
+       (void) strncpy(data->mit_id,argv[U_MITID],sizeof(data->mit_id));
+       (void) strncpy(data->uid,argv[U_UID],sizeof(data->uid));
 #ifdef DEBUG
        fprintf(stderr,"Found in database:\n");
        fprintf(stderr,"   Registration status: %d\n",data->reg_status);
@@ -440,45 +303,28 @@ int db_callproc(argc,argv,queue)
 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_name;              /* Name of query */
-    int q_argc = 2;            /* Number of arguments for query */
-    char *q_argv[2];           /* Arguments to query */
-    int status = 0;            /* Query return status */
+    int q_argc;                        /* Number of arguments for query */
+    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 = 0;                /* Have we verified the user? */
+    short verified = FALSE;    /* Have we verified the user? */
 
     /* Zero the mit_id field in the formatted packet structure.  This
        being zeroed means that no user was found. */
     bzero(message->db.mit_id,sizeof(message->db.mit_id));
     
-    /* First, make sure that there are no wild cards in the names!
-       Just think.  A user giving his name as * * could tie up this
-       server for eight hours and could tie up the SMS database
-       for quite a while as well. */
-    if (index(message->first,'*') || index(message->first,'?') ||
-       index(message->last,'*') || index(message->last,'?'))
-    {
-       /* Act like this name couldn't be found in the SMS database. 
-          This is okay because first of all, we want the user to think
-          that * * is an invalid name, and secondly, it really is; the
-          SMS library checks to make sure that names don't contain these
-          characters when they are entered. */
-       status = SMS_NO_MATCH;
-#ifdef DEBUG
-       fprintf(stderr,"%s %s contains wild cards.\n",message->first,
-               message->last);
-#endif DEBUG
-    }
-
-    if (!status)
+    if (status == SUCCESS)
     {
-       /* Get ready to make an SMS query */
-       q_name = "get_user_by_name";
+       /* Get ready to make an Moira query */
+       q_name = "get_user_account_by_name";
+       q_argc = GUBN_ARGS;     /* #defined in this routine */
        q_argv[0] = message->first;
        q_argv[1] = message->last;
        
@@ -486,13 +332,13 @@ int find_user(message)
        queue = sq_create();
        
        /* Do it */
-       status = sms_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
+       status = mr_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
        
 #ifdef DEBUG
-       com_err(whoami,status,"%d returned by get_user_by_name",status);
+       fprintf(stderr," %d returned by get_user_by_name\n",status);
 #endif
        
-       if (status == SMS_SUCCESS) 
+       if (status == MR_SUCCESS) 
        {
            /* Traverse the list, freeing data as we go.  If sq_get_data()
               returns zero if there is no more data on the queue. */
@@ -500,15 +346,15 @@ int find_user(message)
            {
                if (!verified)
                    /* parse_encrypted returns zero on success */
-                   verified = !parse_encrypted(message,data);
-               free(data);
+                   verified = (parse_encrypted(message,data) == SUCCESS);
+               free((char *)data);
            }
        }
+
+       /* Destroy the queue */
+       sq_destroy(queue);
     }
     
-    /* Destroy the queue */
-    sq_destroy(queue);
-
 #ifdef DEBUG
     fprintf(stderr,"Returned from find_user\n");
     fprintf(stderr,"   MIT ID: %s\n", message->db.mit_id);
@@ -521,142 +367,34 @@ int find_user(message)
     return status;
 }
 
-parse_pkt(packet, pktlen, seqnop, message)
-  char *packet;
-  int pktlen;
-  u_long *seqnop;
-  struct msg *message;
-  /* This routine checks a packet and puts the information in it in
-       a structure if it is valid. */
-{
-    int status = 0;            /* Error status */
-
-    com_err(whoami,0,"Packet received");
-
-    if (pktlen < 4) status = UREG_BROKEN_PACKET;
-    if (!status)
-    {
-       /* Extract the user registartion protocol version from the packet */
-       bcopy(packet, (char *)&message->version, sizeof(long));
-       /* Convert byte order from network to host */
-       message->version = ntohl(message->version);
-       /* Verify version */
-       if (message->version != CUR_UREG_VERSION) 
-           status = UREG_WRONG_VERSION;
-    }
-
-    if (!status)
-    {
-       packet += 4;
-       pktlen -= 4;
-       
-       if (pktlen < 4)
-           status = UREG_BROKEN_PACKET;
-    }
-
-    if (!status)
-    {
-       /* Extract the sequence number from the packet */
-       bcopy(packet, (char *)seqnop, sizeof(long));
-       
-       packet += 4;
-       pktlen -= 4;
-       
-       if (pktlen < 4)
-           status = UREG_BROKEN_PACKET;
-    }
-
-    if (!status)
-    {
-       /* Extract the request from the packet */
-       bcopy(packet, (char *)(&message->request), sizeof(long));
-       message->request = ntohl(message->request);
-       packet += 4;
-       pktlen -= 4;
-       
-       /* Extract first name from the packet */
-       message->first = packet;
-       
-       /* Scan forward until null appears in the packet or there
-          is no more packet! */
-       for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
-       if (pktlen <= 0) 
-           status = UREG_BROKEN_PACKET;
-    }
-    
-    if (!status)
-    {
-       /* Skip over the null */
-       packet++, pktlen--;
-       
-       /* Extract last name from the packet */
-       message->last = packet;
-       
-       for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
-       if (pktlen <= 0)
-           status = UREG_BROKEN_PACKET;
-    }
-
-    if (!status)
-    {
-       packet++, pktlen--;
-       
-       if (pktlen <= 0)
-           status = UREG_BROKEN_PACKET;
-    }
-
-    /* Extract MIT id information from packet */
-    message->encrypted = packet;
-    message->encrypted_len = pktlen;
-    
-    if (status == SUCCESS)
-    {
-#ifdef DEBUG
-       com_err(whoami,status,"%s\n%s%d\n%s%d\n%s%s\n%s%s",
-               "Packet parsed successfully.  Packet contains:",
-               "   Protocol version: ",message->version,
-               "   Request: ",message->request,
-               "   First name: ",message->first,
-               "   Last name: ",message->last);
-#else /* DEBUG */
-       com_err(whoami,status,"Request %d for %s %s",message->request,
-               message->first,message->last);
-#endif DEBUG    
-    }
-    else
-       com_err(whoami,status,"- parse packet failed.");
-
-    return status;
-}
-
 int verify_user(message,retval)
   struct msg *message;
   char *retval;
+  /* This routine determines whether a user is in the databse and returns
+     his state so that other routines can figure out whether he is the 
+     correct state for various transactions. */
+     
 {
-    int status = 0;            /* Return status */
+    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 
        parse_encrypted().) */
-    /* Note that find_user() does not return an error status; see the
-       comment on find_user().  parse_pkt's return status should
-       reflect whether or not the packet could be parsed, not
-       whether the user could be found. */
 
     status = find_user(message);
 
-    /* If SMS coudn't find the user */
-    if (status == SMS_NO_MATCH) 
+    /* If Moira coudn't find the user */
+    if (status == MR_NO_MATCH) 
        status = UREG_USER_NOT_FOUND;
-    else if (status == SMS_SUCCESS)
+    else if (status == MR_SUCCESS)
     {
        /* If the information sent over in the packet did not point to a
           valid user, the mit_id field in the formatted packet structure
           will be empty. */
-       if (message->db.mit_id[0] == 0)
+       if (message->db.mit_id[0] == NULL)
            status = UREG_USER_NOT_FOUND;
        /* If the user was found but the registration has already started,
           use this as the status */
@@ -664,52 +402,99 @@ int verify_user(message,retval)
        {
            switch (message->db.reg_status)
            {
-               /* These should be defined in a header. ### */
-             case 0:
+             case US_NO_LOGIN_YET:
                status = SUCCESS;
                break;
-             case 1:
+             case US_REGISTERED:
                status = UREG_ALREADY_REGISTERED;
                break;
-             case 2:
+             case US_NO_PASSWD:
                status = UREG_NO_PASSWD_YET;
                break;
-             case 3:
+             case US_DELETED:
                status = UREG_DELETED;
                break;
-             case 4:
+             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;
-               /* ### Send email... */
+               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
               it in the error message it will give the user. */
-           strcpy(retval,message->db.login);
+           (void) strcpy(retval,message->db.login);
        }
     }
     
-    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()
 {
-    char realm[REALM_SZ];      /* Kerberos realm */
-    int status = 0;            /* 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. */
-    if ((status = get_krbrlm(realm, 1)) != KSUCCESS) 
+    /* principal, instance, realm, service, service instance, life, file */
+    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
+    else {
+       com_err(whoami, status, "Succeeded in getting admin tickets");
+    }
+#endif
 
-    if (!status)
-       if (status = get_svc_in_tkt("register", "sms", realm,
-                               "changepw", "kerberos",
-                               1, KEYFILE))
-           status += krb_err_base;
+    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;
 }
@@ -721,42 +506,89 @@ int null_callproc(argc,argv,message)
   /* This routine is a null callback that should be used for queries that
      do not return tuples.  If it ever gets called, something is wrong. */
 {
-    /* This routine should never be called; issue an error. ### */
-    return NON_ZERO;
+    critical_alert(FAIL_INST,"Something returned from an update query.");
+    return FAILURE;
 }
 
-int do_admin_call(login, passwd, uid)
+/*
+ * This routine reserves a principal in kerberos by setting up a 
+ * principal with a random initial key.
+ */
+int reserve_krb(login)
   char *login;
-  char *passwd;
-  char *uid;
 {
-    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;
 
-    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 ### */
-       bzero(uid_buf,sizeof(uid_buf));
-       (void) sprintf(uid_buf, "%013d", uid);
+#ifdef DEBUG
+    com_err(whoami, 0, "Entering reserve_krb");
+#endif DEBUG
+
+    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;
-           /* Send email... ### */
+       (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();
-    return status;
+    return(status);
 }
 
 int reserve_user(message,retval)
@@ -764,104 +596,135 @@ 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 */
-    int status = 0;            /* General purpose error status */
+    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 */
-    int invalid = 0;           /* True if login name is invalid */
 
-    /* Log that we are about to resever a user. */
-    com_err(whoami,status,"reserve_user %s %s", 
+    /* Log that we are about to reserve a user. */
+    com_err(whoami, 0, "reserving user %s %s", 
            message->first, message->last);
     
     /* Check to make sure that we can verify this user. */
     if ((status = verify_user(message,retval)) == SUCCESS)
     {
+       /* Get the requested login name from leftover packet information. */
        login = message->leftover;
-       /* The login name currently is allowed to contain lowercase letters, 
-          numbers, underscore characters, and periods in any position and
-          is allowed to be from three to eight characters in length. */
-       
-       /* Check the username for validity. */
-       
-       if ((strlen(login) < 3) || (strlen(login) > 8))
+
+       /* 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)
-    {
-       for (i = 0; ((i < strlen(login)) && (!invalid)); i++)
-           invalid = (!islower(login[i]) && !isdigit(login[i]) &&
-                      (login[i] != '_') && (login[i] != '.'));
-       if (invalid)
+    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)
+    if (status == SUCCESS)
     {
        /* Now that we have a valid user with a valid login... */
 
-       /* First, try to reserve the user in SMS. */
-       sprintf(fstype_buf,"%d",SMS_FS_STUDENT);
+       /* First, try to reserve the user in Moira. */
+       (void) sprintf(fstype_buf,"%d",MR_FS_STUDENT);
        q_name = "register_user";
        q_argv[0] = message->db.uid;
        q_argv[1] = login;
        q_argv[2] = fstype_buf;
        q_argc = 3;
-       status = sms_query(q_name,q_argc,q_argv,null_callproc,0);
+       status = mr_query(q_name,q_argc,q_argv,null_callproc,(char *)0);
        switch (status)
        {
-         case SMS_SUCCESS:
+         case MR_SUCCESS:
            status = SUCCESS;
            break;
-         case SMS_IN_USE:
+         case MR_IN_USE:
            status = UREG_LOGIN_USED;
            break;
+         case MR_DEADLOCK:
+           status = UREG_MISC_ERROR;
+           break;
          default:
+           critical_alert(FAIL_INST,"%s returned from register_user.",
+                          error_message(status));
            status = UREG_MISC_ERROR;
-           /* Send email... ### */
            break;
        }
     }
-    if (!status)
+
+    if (status == SUCCESS)
     {
-       /* SMS login was successfully created; try to reserve kerberos
-          principal. */
-       /* If this routine fails, store in 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)
-           strcpy(retval, login);
+       /* 
+        * 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;
-    /* This routine updates a users registration status to zero, meaning
-     fully registered. */
-    /* This NEEDS to have the numbers #defined! ### */
+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);
 
     q_name = "update_user_status";
     q_argc = 2;
     q_argv[0] = login;
-    q_argv[1] = "0";           /* Fully registered */
-    if ((status = sms_query(q_name, q_argc, q_argv, null_callproc,
-                           (char *)0)) != SMS_SUCCESS)
-    {
-       /* Send email ### */
+    q_argv[1] = state;
+    if ((status = mr_query(q_name, q_argc, q_argv, null_callproc,
+                           (char *)0)) != MR_SUCCESS) {
+       if (status == MR_DEADLOCK)
+         status = UREG_MISC_ERROR;
+       else
+         critical_alert(FAIL_INST,"%s returned from update_user_status.",
+                        error_message(status));
     }
-    
-    com_err(whoami,status,"returned from set_final_status");
+    if (status)
+       com_err(whoami, status, " returned from set_final_status");
+    else
+       com_err(whoami, 0, "Final status set");
     return status;
 }
 
@@ -871,11 +734,10 @@ int set_password(message,retval)
   char *retval;
   /* This routine is used to set the initial password for the new user. */
 {
-    int status = 0;            /* Return status */
+    int status = SUCCESS;      /* Return status */
     char *passwd;              /* User's password */
-    char uid_buf[20];          /* Buffer to hold uid for Kerberos ### */
 
-    com_err(whoami, 0, " set_password %s %s\n",
+    com_err(whoami, 0, "setting password %s %s",
            message->first, message->last);
 
     status = verify_user(message,retval);
@@ -884,34 +746,322 @@ int set_password(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 */
-           strcpy(retval,message->db.login);
+           (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;
+    int  i;
+
+    if (argc != U_END) {
+       critical_alert(FAIL_INST,
+                      "Wrong number of args returned from get_user_by_uid");
+       status = MR_ABORT;
+    } else {
+       qargv[U_NAME] = strsave(argv[U_NAME]);
+       for (i = 1; i < U_MODTIME; i++)
+         qargv[i+1] = strsave(argv[i]);
+       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 = mr_query("get_user_account_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";
+       q_argv[U_SIGNATURE+1] = "";
+       status = mr_query("update_user_account", U_MODTIME+1, q_argv,
+                          null_callproc, NULL);
+       switch (status)
+       {
+         case MR_SUCCESS:
+           status = SUCCESS;
+           break;
+         case MR_IN_USE:
+         case MR_NOT_UNIQUE:
+           status = UREG_LOGIN_USED;
+           break;
+         case MR_DEADLOCK:
+           status = UREG_MISC_ERROR;
+           break;
+         default:
+           critical_alert(FAIL_INST,"%s returned from update_user_account.",
+                          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);
+}
+
+
+/* Find out of someone's secure instance password is set.
+ * Returns UREG_ALREADY_REGISTERED if set, SUCCESS (0) if not.
  */
+
+int get_secure(message, retval)
+struct msg *message;
+char *retval;
+{
+    int status;
+    char *argv[U_END];
+
+    com_err(whoami, 0, "checking status of secure password for %s",
+           message->first);
+    argv[0] = message->first;
+    status = mr_query("get_user_account_by_login", 1, argv, getuserinfo, argv);
+    if (status != SUCCESS) {
+       com_err(whoami, status, " while getting user info");
+       return(status);
+    }
+    if (atoi(argv[U_SECURE + 1]))
+      return UREG_ALREADY_REGISTERED;
+    return SUCCESS;
+}
+
+
+/* Set someone's secure instance password. */
+
+int set_secure(message, retval)
+struct msg *message;
+char *retval;
+{
+    int status, i;
+    char *argv[U_END], hostbuf[256], *bp, *p, buf[512], *passwd, *id;
+    KTEXT_ST creds;
+    AUTH_DAT auth;
+    C_Block key;
+    Key_schedule keys;
+    Kadm_vals kv;
+    u_long *lkey = (u_long *)key;
+    struct timeval now;
+    static int inited = 0;
+    static char *host;
+
+    if (!inited) {
+       inited++;
+       if (gethostname(hostbuf, sizeof(hostbuf)) < 0)
+         com_err(whoami, errno, "getting local hostname");
+       host = strsave(krb_get_phost(hostbuf));
+    }
+
+    com_err(whoami, 0, "setting secure passwd for %s", message->first);
+    argv[0] = message->first;
+    status = mr_query("get_user_account_by_login", 1, argv, getuserinfo, argv);
+    if (status != SUCCESS) {
+       com_err(whoami, status, " while getting user info");
+       return(status);
+    }
+    if (atoi(argv[U_SECURE + 1])) {
+       com_err(whoami, UREG_ALREADY_REGISTERED, "in set_secure()");
+       return UREG_ALREADY_REGISTERED;
+    }
+
+    bp = message->encrypted;
+    /* round up to word boundary */
+    bp = (char *)((((u_long)bp + 3) >> 2) << 2);
+    
+    creds.length = ntohl(*((int *)bp));
+    bp += sizeof(int);
+    bcopy(bp, creds.dat, creds.length);
+    creds.mbz = 0;
+    bp += creds.length;
+
+#ifdef DEBUG
+    com_err(whoami, 0, "Cred: length %d", creds.length);
+    for (i = 0; i < creds.length; i += 16)
+      com_err(whoami, 0, " %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x",
+             creds.dat[i+0], creds.dat[i+1], creds.dat[i+2], creds.dat[i+3],
+             creds.dat[i+4], creds.dat[i+5], creds.dat[i+6], creds.dat[i+7],
+             creds.dat[i+8], creds.dat[i+9], creds.dat[i+10], creds.dat[i+11],
+             creds.dat[i+12], creds.dat[i+13], creds.dat[i+14], creds.dat[i+15]);
+#endif /* DEBUG */
+    
+    status = krb_rd_req(&creds, "changepw", host, cur_req_sender(),
+                       &auth, "");
+    if (status) {
+       status += krb_err_base;
+       com_err(whoami, status, " verifying credentials in set_secure()");
+       return(status);
+    }
+
+    message->leftover_len = ntohl(*((int*)(bp)));
+    bp += sizeof(int);
+    message->leftover = bp;
+
+    des_key_sched(auth.session, keys);
+    des_pcbc_encrypt(message->leftover, buf, message->leftover_len,
+                    keys, auth.session, 0);
+
+    id = buf;
+    passwd = index(buf, ',');
+    *passwd++ = 0;
+#ifdef DEBUG
+    com_err(whoami, 0, "Got id: %s, passwd %d chars", id, strlen(passwd));
+#endif
+
+    if (strcmp(id, argv[U_MITID + 1])) {
+       char buf[32];
+
+       EncryptID(buf, id, argv[U_FIRST+1], argv[U_LAST+1]);
+       if (strcmp(buf, argv[U_MITID + 1])) {
+           status = UREG_USER_NOT_FOUND;
+           com_err(whoami, status, "IDs mismatch: %s (%s), %s", id, buf,
+                   argv[U_MITID + 1]);
+           return status;
+       }
+    }
+
+    /* now do actual password setting stuff */
+
+    if ((status = ureg_kadm_init()) != SUCCESS) {
+       com_err(whoami, status, "initing kadm stuff");
+       return(status);
+    }
+
+    bzero((char *)&kv, sizeof(kv));
+    SET_FIELD(KADM_DESKEY, kv.fields);
+    SET_FIELD(KADM_NAME, kv.fields);
+    SET_FIELD(KADM_INST, kv.fields);
+    (void) des_string_to_key(passwd, key);
+    kv.key_low = htonl(lkey[0]);
+    kv.key_high = htonl(lkey[1]);
+    strcpy(kv.name, message->first);
+    strcpy(kv.instance, "extra");
+
+    if ((status = kadm_add(&kv)) != KADM_SUCCESS) {
+       com_err(whoami, status, " while creating kerberos principal");
+       return(status);
+    }
+
+    argv[0] = message->first;
+    argv[1] = buf;
+    gettimeofday(&now, NULL);
+    sprintf(buf, "%d", now.tv_sec);
+    status = mr_query("update_user_security_status", 2, argv, getuserinfo, argv);
+    if (status != SUCCESS) {
+       com_err(whoami, status, " while updating user status");
+       return(status);
+    }
+    return SUCCESS;
+}
This page took 1.196462 seconds and 4 git commands to generate.