From: zacheiss Date: Wed, 29 Jun 2005 06:39:35 +0000 (+0000) Subject: Add CLGN (server) / LOGC (client) protocol option to check if a username X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/commitdiff_plain/276949c145f49f65b73fa392ca34dd2fbc250062 Add CLGN (server) / LOGC (client) protocol option to check if a username is available and give the user a chance to confirm they want to use it. Also fix missing whitespace in errors file for BAD_PIN error code. --- diff --git a/reg_svr/errors b/reg_svr/errors index eb60d904..8ce63775 100644 --- a/reg_svr/errors +++ b/reg_svr/errors @@ -93,8 +93,10 @@ You should be able to log in by tomorrow morning using your Athena username (%s) and the password you chose. Welcome to Athena! -#21 BAD_PIN +# 21 BAD_PIN The PIN you typed was incorrect. Please make sure you typed it correctly. If you do not remember your PIN, you will need to contact the Athena User Accounts Office in N42-105A, x3-1325. +# 22 USERNAME_AVAILABLE +The username "%s" is available for you to use. diff --git a/reg_svr/protocol.c b/reg_svr/protocol.c index aa82a83f..e6e4a84c 100644 --- a/reg_svr/protocol.c +++ b/reg_svr/protocol.c @@ -44,6 +44,7 @@ struct _handler { { "PSWD", PSWD }, { "QUIT", QUIT }, { "SPIN", SPIN }, + { "CLGN", CLGN }, { NULL, NULL } }; diff --git a/reg_svr/reg_svr.h b/reg_svr/reg_svr.h index 516bae9d..c66c0183 100644 --- a/reg_svr/reg_svr.h +++ b/reg_svr/reg_svr.h @@ -23,6 +23,7 @@ typedef struct reg_client { void RIFO(reg_client *rc, int argc, char **argv); void SWRD(reg_client *rc, int argc, char **argv); void SPIN(reg_client *rc, int argc, char **argv); +void CLGN(reg_client *rc, int argc, char **argv); void LOGN(reg_client *rc, int argc, char **argv); void PSWD(reg_client *rc, int argc, char **argv); void QUIT(reg_client *rc, int argc, char **argv); @@ -40,7 +41,7 @@ enum { NO_MESSAGE, INTERNAL_ERROR, PROTOCOL_ERROR, DATABASE_CLOSED, BAD_SIX_WORDS, BAD_USERNAME, USERNAME_UNAVAILABLE, RESERVED_USERNAME_UNAVAILABLE, USERNAME_OK, PASSWORD_SHORT, PASSWORD_SIMPLE, PASSWORD_SAMPLE, KADM_ERROR, DONE, BAD_PIN, - NUM_REG_ERRORS }; + USERNAME_AVAILABLE, NUM_REG_ERRORS }; #define TIMEOUT 300 /* 5 minutes */ diff --git a/reg_svr/reg_svr.pc b/reg_svr/reg_svr.pc index 43e52e30..4a592f80 100644 --- a/reg_svr/reg_svr.pc +++ b/reg_svr/reg_svr.pc @@ -42,6 +42,7 @@ RCSID("$Header$"); char *whoami, *hostname, *shorthostname; char *find_usernames(char *first, char *middle, char *last); +int check_username_available(char *username); void fixname(char *name); int register_user(int uid, char *username); void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar); @@ -534,6 +535,80 @@ void SPIN(reg_client *rc, int argc, char **argv) } } +void CLGN(reg_client *rc, int argc, char **argv) +{ + int i; + char *login; + long status; + + if (!rc->uid || rc->id || rc->username || argc != 1) + { + reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL); + return; + } + + login = argv[0]; + + /* make sure someone's not trying to overrun reply */ + if (strlen(login) > 100) + { + com_err(whoami, 0, "Buffer overrun attempted? Closing connection"); + rc->lastmod = 0; + return; + } + + if ((strlen(login) < 3) || (strlen(login) > USERS_LOGIN_SIZE - 1) || + (login[0] == '_') || isdigit(login[0])) + { + reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login, + 3, USERS_LOGIN_SIZE - 1); + return; + } + + for (i = 0; i < strlen(login); i++) + { + if (!islower(login[i]) && !isdigit(login[i]) && (login[i] != '_')) + { + reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login, + 3, USERS_LOGIN_SIZE - 1); + return; + } + } + + status = check_kerberos(login); + if (status == MR_SUCCESS) + { + status = check_username_available(login); + if (status == MR_SUCCESS) + { + reply(rc, USERNAME_AVAILABLE, "LOGC", "c", login, login); + return; + } + } + + if (status == MR_IN_USE) + { + if (rc->reserved_username) + { + reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL, + rc->username); + return; + } + reply(rc, USERNAME_UNAVAILABLE, "GETL", "c", rc->suggestions); + return; + } + else if (status == MR_DOWN) + { + reply(rc, DATABASE_CLOSED, "INIT", "c", NULL); + return; + } + else if (status != MR_SUCCESS) + { + reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(status)); + return; + } +} + void LOGN(reg_client *rc, int argc, char **argv) { int i; @@ -882,6 +957,37 @@ char *find_usernames(char *first, char *middle, char *last) return unames; } +/* This does the database-side checks to make sure a username is + * available. + */ +int check_username_available(char *username) +{ + int count; + + EXEC SQL SELECT COUNT(login) INTO :count FROM users + WHERE login = :username; + if (sqlca.sqlcode) + return MR_DBMS_ERR; + if (count != 0) + return MR_IN_USE; + + EXEC SQL SELECT COUNT(name) INTO :count FROM list + WHERE name = :username; + if (sqlca.sqlcode) + return MR_DBMS_ERR; + if (count != 0) + return MR_IN_USE; + + EXEC SQL SELECT COUNT(label) INTO :count FROM filesys + WHERE label = :username; + if (sqlca.sqlcode) + return MR_DBMS_ERR; + if (count != 0) + return MR_IN_USE; + + return MR_SUCCESS; +} + void fixname(char *name) { char *s, *d;