]> andersk Git - moira.git/blobdiff - reg_svr/reg_svr.c
catch deadlock errors
[moira.git] / reg_svr / reg_svr.c
index b67163066bea85ceee45a97769e1dfcc75c89d45..b7bd0029f8abea058fd069f254ddae4c7c2df3b8 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.
  *
- *      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.11  1988-08-02 01:41:38  qjb
- *      Yet another almost finished version.  Ready for attack of kerberos problems
- *      and testing.
- *
- * Revision 1.10  88/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
+ *      SMS server as it is linked with libsmsglue which bypasses
+ *      the network protocol.
  */
 
 #ifndef lint
 static char *rcsid_reg_svr_c = "$Header$";
 #endif lint
 
-#include <stdio.h>
-#include <strings.h>
-#include <ctype.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 <errno.h>
-#include <ctype.h>
-#include "ureg_err.h"
-#include "ureg_proto.h"
-#include "sms.h"
-#include "sms_app.h"
-#include "infodefs.h"
+#include <mit-copyright.h>
+#include "reg_svr.h"
 #include "admin_server.h"
 #include "admin_err.h"
+#include "krb_et.h"
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#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 MIN_UNAME 3            /* Username must be between three and */
-#define MAX_UNAME 8            /*    eight characters long. */
-#define CRYPT_LEN 14           /* crypt() returns a 13 char string */
-#define LOGIN_LEN MAX_UNAME + 1        /* Leave room for a null */
-#define UID_LEN 7              /* Allow room for a 16 bit number */
-
-#define DEBUG
-
-extern char *strdup();
-extern char *malloc();
-extern int krb_err_base;
 extern char admin_errmsg[];
 
-extern char *whoami;           /* Name of program - used by libraries */
-extern int errno;              /* Unix error number */
+static char krbhst[BUFSIZ];    /* kerberos server name */
+static char krbrealm[REALM_SZ];        /* kerberos realm name */
+void reg_com_err_hook();
 
-/* 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 in a 
-   more convenient format and also stores some information obtained 
-   from the database that will be needed for each transaction.  It
-   initialized from format_pkt() and find_user(). */
-struct msg
-{    
-    U_32BIT version;           /* User registration protocol version */
-    U_32BIT 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 */
-};
 
 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;                        /* Length of packet */
-    U_32BIT seqno;             /* Sequence number for packet transmission */
     struct msg message;                /* Storage for parsed packet */
     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();         /* Make 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];
-
+    
+    /* 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 */
     init_ureg_err_tbl();
     
-    /* Get service information from /etc/services */
-    if ((sp = getservbyname("sms_ureg", "udp")) == NULL
+    /* Connect to the SMS server */
+    if ((status = sms_connect(SMS_SERVER)) != SMS_SUCCESS
     {
-       com_err(whoami, errno, " unknown service sms_ureg/udp");
+       com_err(whoami, status, " on connect");
        exit(1);
     }
     
-    /* Get an internet style datagram socket */
-    if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0
+    /* Authorize, telling the server who you are */
+    if ((status = sms_auth(whoami)) != SMS_SUCCESS
     {
-       com_err(whoami,errno," socket");
+       com_err(whoami, status, " on auth");
        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) 
-    {
-       com_err(whoami,errno," bind");
+    if (status = krb_get_lrealm(krbrealm, 1)) {
+       status += ERROR_TABLE_BASE_krb;
+       com_err(whoami, status, " fetching kerberos realm");
        exit(1);
     }
     
-    /* Connect to the SMS server */
-    if ((status = sms_connect()) != SMS_SUCCESS) 
-    {
-       com_err(whoami, status, " on connect");
+    if (status = krb_get_krbhst(krbhst, krbrealm, 1)) {
+       status += ERROR_TABLE_BASE_krb;
+       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;
     }
-    
-    /* Authorize, telling the server who you are */
-    if ((status = sms_auth(whoami)) != SMS_SUCCESS) 
-    {
-       com_err(whoami, status, " on auth");
+
+    journal = fopen(JOURNAL, "a");
+    if (journal == NULL) {
+       com_err(whoami, errno, " while opening journal file");
        exit(1);
     }
-
-    /* Use com_err or output to stderr for all log messages. */    
-#ifdef DEBUG
-    fprintf(stderr,"*** Debugging messages enabled. ***\n");
-#endif DEBUG
-
+    
+    /* Allow request layer to initialize */
+    req_initialize();
+    
     /* 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 */
-       if ((pktlen = recvfrom(s,packet,sizeof(packet),0,&sin,&addrlen)) < 0) 
-       {
-           com_err(whoami,errno," recvfrom");
-           /* Don't worry if error is interrupted system call. */
-           if (errno == EINTR) continue;
-           exit(1);
-       }
+       get_request(&message);
        
-       /* Parse a request packet */
-       if ((status = parse_pkt(packet, pktlen, &seqno, &message)) != SUCCESS) 
-       {
-           /* If error, format packet to send back to the client */
-           pktlen = sizeof(packet);
-           format_pkt(packet, &pktlen, seqno, status, (char *)NULL);
-           /* Report the error the the client */
-           (void)  sendto(s, packet, pktlen, 0, &sin, addrlen);
-           continue;
-       }
-       
-       /* do action */
        switch((int)message.request) 
        {
          case UREG_VERIFY_USER:
@@ -239,64 +115,29 @@ 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;
          default:
            status = UREG_UNKNOWN_REQUEST;
-           /* Send email ### */
+           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);
-       (void) sendto(s, packet, pktlen, 0, &sin, addrlen);
+       report(status, retval);
     }
 }
 
-void format_pkt(packet, pktlenp, seqno, status, message)
-  char *packet;
-  int *pktlenp;
-  U_32BIT seqno;
-  int status;
-  char *message;
-  /* This routine prepares a packet to send back to the client. */
-{
-    /* Convert byte order to network byte order */
-    U_32BIT vers = htonl((U_32BIT)CUR_UREG_VERSION);
-    status = htonl((U_32BIT)status);
-    
-    /* Put current user registration protocol 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 encrypted ID */
-  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. */
+/* This is necessary so that this server can know where to put its
+   tickets. */
+char *tkt_string()
 {
-    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));
+    return("/tmp/tkt_ureg");
 }
 
 int parse_encrypted(message,data)
@@ -306,8 +147,8 @@ int parse_encrypted(message,data)
    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 encrypt_mitid() ###
-   resulting in the form that would appear in the SMS database.  This is
+   The plain text ID number was encrypted via EncryptID() 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 is appended.  The whole
@@ -349,10 +190,6 @@ int parse_encrypted(message,data)
        padded. */
     pcbc_encrypt(message->encrypted,decrypt, decrypt_len, sched, key, 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
@@ -376,12 +213,12 @@ int parse_encrypted(message,data)
     len = message->encrypted_len - (temp - decrypt);
     
     /* Now compare encrypted ID's don't match. */
-    if (strcmp(hashid, data->mit_id)) status = NON_ZERO;
+    if (strcmp(hashid, data->mit_id)) status = FAILURE;
     if (status == SUCCESS)
     {
-       encrypt_mitid(recrypt, idnumber, message->first, message->last);
+       EncryptID(recrypt, idnumber, message->first, message->last);
        /* Now compare encrypted plain text to ID from database. */
-       if (strcmp(recrypt, data->mit_id)) status = NON_ZERO;
+       if (strcmp(recrypt, data->mit_id)) status = FAILURE;
     }
     
     if (status == SUCCESS)
@@ -425,8 +262,10 @@ int db_callproc(argc,argv,queue)
 
     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_by_name.");
+       status = SMS_ABORT;
     }
     else
     {
@@ -455,7 +294,7 @@ int find_user(message)
    him/her in the SMS database.  It returns the status of the SMS
    query that it calls. */
 {
-#define GUBN_ARGS 2            /* Arguements needed by get_uer_by_name */
+#define GUBN_ARGS 2            /* Arguements needed by get_user_by_name */
     char *q_name;              /* Name of query */
     int q_argc;                        /* Number of arguments for query */
     char *q_argv[GUBN_ARGS];   /* Arguments to query */
@@ -469,25 +308,6 @@ int find_user(message)
        being zeroed means that no user was found. */
     bzero(message->db.mit_id,sizeof(message->db.mit_id));
     
-    /* 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 == SUCCESS)
     {
        /* Get ready to make an SMS query */
@@ -503,7 +323,7 @@ int find_user(message)
        status = sms_query(q_name,q_argc,q_argv,db_callproc,(char *)queue);
        
 #ifdef DEBUG
-       fprintf(stderr," %d returned by get_user_by_name",status);
+       fprintf(stderr," %d returned by get_user_by_name\n",status);
 #endif
        
        if (status == SMS_SUCCESS) 
@@ -535,114 +355,6 @@ int find_user(message)
     return status;
 }
 
-parse_pkt(packet, pktlen, seqnop, message)
-  char *packet;
-  int pktlen;
-  U_32BIT *seqnop;
-  struct msg *message;
-  /* This routine checks a packet and puts the information in it in
-     a structure if it is valid. */
-{
-    int status = SUCCESS;      /* Error status */
-
-    com_err(whoami,0,"Packet received");
-
-    if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
-    if (status == SUCCESS)
-    {
-       /* Extract the user registration 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 == SUCCESS)
-    {
-       packet += sizeof(U_32BIT);
-       pktlen -= sizeof(U_32BIT);
-       
-       if (pktlen < sizeof(U_32BIT))
-           status = UREG_BROKEN_PACKET;
-    }
-
-    if (status == SUCCESS)
-    {
-       /* Extract the sequence number from the packet */
-       bcopy(packet, (char *)seqnop, sizeof(long));
-       
-       packet += sizeof(U_32BIT);
-       pktlen -= sizeof(U_32BIT);
-       
-       if (pktlen < sizeof(U_32BIT))
-           status = UREG_BROKEN_PACKET;
-    }
-
-    if (status == SUCCESS)
-    {
-       /* Extract the request from the packet */
-       bcopy(packet, (char *)(&message->request), sizeof(U_32BIT));
-       message->request = ntohl(message->request);
-       packet += sizeof(U_32BIT);
-       pktlen -= sizeof(U_32BIT);
-       
-       /* 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 == SUCCESS)
-    {
-       /* 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 == SUCCESS)
-    {
-       packet++, pktlen--;
-       
-       if (pktlen <= 0)
-           status = UREG_BROKEN_PACKET;
-    }
-
-    /* Extract encrypted 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;
@@ -693,10 +405,16 @@ int verify_user(message,retval)
              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;
              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
@@ -712,19 +430,20 @@ int verify_user(message,retval)
        
 int ureg_get_tkt()
 {
-    char realm[REALM_SZ];      /* Kerberos realm */
     int status = SUCCESS;      /* Return status */
 
     /* Get keys for interacting with Kerberos admin server. */
-    if ((status = get_krbrlm(realm, 1)) != KSUCCESS) 
-       status += krb_err_base;
+    /* principal, instance, realm, service, service instance, life, file */
+    if (status = krb_get_svc_in_tkt("register", "sms", krbrealm, "changepw", 
+                               krbhst, 1, KEYFILE))
+       status += ERROR_TABLE_BASE_krb;
 
+#ifdef DEBUG
     if (status == SUCCESS)
-       /* principal, instance, realm, service, service instance, life, file */
-       if (status = get_svc_in_tkt("register", "sms", realm, "changepw", 
-                                   "kerberos", 1, KEYFILE))
-           status += krb_err_base;
-
+       com_err(whoami,status,"Succeeded in getting tickets.");
+    else
+       com_err(whoami,status,"Failed to get tickets.");
+#endif
     return status;
 }
 
@@ -735,8 +454,8 @@ 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. */
 {
-    /* Send email... ### */
-    return NON_ZERO;
+    critical_alert(FAIL_INST,"Something returned from an update query.");
+    return FAILURE;
 }
 
 int do_admin_call(login, passwd, uid)
@@ -749,15 +468,18 @@ int do_admin_call(login, passwd, uid)
     int status;                        /* Error status */
     char uid_buf[20];          /* Holds uid for kerberos */
 
+    com_err(whoami,0,"Entering do_admin_call");
+
     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 ### */
+       /* 13 chars of placebo for backwards-compatability - the admin
+          server protocol reqires this. */
        bzero(uid_buf,sizeof(uid_buf));
-       (void) sprintf(uid_buf, "%013d", uid);
+       (void) sprintf(uid_buf, "%13s", uid);
        
        if ((status = admin_call(ADMIN_ADD_NEW_KEY_ATTR, login, 
                                 "", passwd, uid_buf)) != KSUCCESS)
@@ -767,11 +489,13 @@ int do_admin_call(login, passwd, uid)
            if (strcmp(admin_errmsg,
                       "Principal already in kerberos database.") == 0)
                status = UREG_KRB_TAKEN;
-           /* Send email... ### */
+           critical_alert(FAIL_INST,"%s is known to Kerberos but not SMS.", 
+                          login);
        }
     }
     
     dest_tkt();
+    com_err(whoami,status," returned from do_admin_call");
     return status;
 }
 
@@ -786,9 +510,8 @@ int reserve_user(message,retval)
     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 = FALSE;       /* True if login name is invalid */
 
-    /* Log that we are about to resever a user. */
+    /* Log that we are about to reserve a user. */
     com_err(whoami, 0, "reserve_user %s %s", 
            message->first, message->last);
     
@@ -800,21 +523,23 @@ int reserve_user(message,retval)
 
        /* 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. */
+          position 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[1] == '_')
            status = UREG_INVALID_UNAME;
     if (status == SUCCESS)
     {
-       for (i = 0; ((i < strlen(login)) && (!invalid)); i++)
-           invalid = (!islower(login[i]) && !isdigit(login[i]) &&
-                      (login[i] != '_') && (login[i] != '.'));
-       if (invalid)
-           status = UREG_INVALID_UNAME;
+       for (i = 0; i < strlen(login); i++)
+           if (!islower(login[i]) && !isdigit(login[i]) && 
+               (login[i] != '_'))
+           {
+               status = UREG_INVALID_UNAME;
+               break;
+           }
     }
     if (status == SUCCESS)
     {
@@ -836,9 +561,13 @@ int reserve_user(message,retval)
          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 register_user.",
+                          error_message(status));
            status = UREG_MISC_ERROR;
-           /* Send email... ### */
            break;
        }
     }
@@ -857,30 +586,40 @@ int reserve_user(message,retval)
     return status;
 }
 
-int set_final_status(login)
-  char *login;
-    /* This routine updates a users registration status to fully 
+int set_final_status(message)
+struct msg *message;
+    /* This routine updates a user's registration status to fully 
        registered. */
 {
+    char *login;
     char *q_name;              /* Name of SMS query */
     int q_argc;                        /* Number of arguments for SMS 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)
-    {
-       /* Send email ### */
+                           (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));
     }
-    
     com_err(whoami,status," returned from set_final_status");
     return status;
 }
@@ -917,20 +656,148 @@ int set_password(message,retval)
            (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");
     
     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 SMS query */
+    char *q_name;              /* Name of SMS 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, "set_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 and numbers in any
+          position 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[1] == '_')
+           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;
+       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)
+    {
+       /* 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)
+           (void) strcpy(retval, login);
+    }
+
+    com_err(whoami, status, " returned from set_identity");
+    
+    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);
+}
This page took 0.186524 seconds and 4 git commands to generate.