* $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:
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)
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
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
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)
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
{
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 */
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 */
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)
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;
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
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;
}
/* 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)
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)
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;
}
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);
/* 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)
{
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;
}
}
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;
}
(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);
+}