[2841] in Moira
reg_svr patches
daemon@ATHENA.MIT.EDU (Garry Zacheiss)
Mon Jun 27 07:46:05 2005
Message-Id: <200506271145.j5RBjouw004128@brad-majors.mit.edu>
To: moiradev@MIT.EDU
Date: Mon, 27 Jun 2005 07:45:50 -0400
From: Garry Zacheiss <zacheiss@MIT.EDU>
These patches to the reg_svr implement functionality that the accounts
consultants have wanted for some time; it adds a protocol operation to
check if the username is available, which is used by new code in the
regapplet (patches to follow) to ask the user a "you can have this
username if you want it. Are you REALLY SURE you want it?" question.
The CLGN() function that got added ends up duplicating some code that is
also in LOGN() because I wanted to be backwards compatible with old
applets that will never end up asking the server to run CLGN().
Also hidden in here is a bug fix to the errors file; it turns out the
space between the # and the numeric error code is necessary for the
parser to work, which I hadn't realized when I added the BAD_PIN code,
although it only results in the reg_svr.log being less pretty.
I've tested this with both an old client and my new modified client, and
gotten the desired results in both cases.
Garry
Index: errors
===================================================================
RCS file: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/reg_svr/errors,v
retrieving revision 1.3
diff -u -r1.3 errors
--- errors 25 Feb 2002 16:41:17 -0000 1.3
+++ errors 27 Jun 2005 09:09:06 -0000
@@ -93,8 +93,10 @@
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.
Index: protocol.c
===================================================================
RCS file: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/reg_svr/protocol.c,v
retrieving revision 1.3
diff -u -r1.3 protocol.c
--- protocol.c 25 Feb 2002 16:41:17 -0000 1.3
+++ protocol.c 27 Jun 2005 04:22:23 -0000
@@ -44,6 +44,7 @@
{ "PSWD", PSWD },
{ "QUIT", QUIT },
{ "SPIN", SPIN },
+ { "CLGN", CLGN },
{ NULL, NULL }
};
Index: reg_svr.h
===================================================================
RCS file: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/reg_svr/reg_svr.h,v
retrieving revision 1.15
diff -u -r1.15 reg_svr.h
--- reg_svr.h 29 Mar 2002 02:23:33 -0000 1.15
+++ reg_svr.h 27 Jun 2005 11:45:15 -0000
@@ -23,6 +23,7 @@
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 @@
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 */
Index: reg_svr.pc
===================================================================
RCS file: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/reg_svr/reg_svr.pc,v
retrieving revision 1.16
diff -u -r1.16 reg_svr.pc
--- reg_svr.pc 1 Jul 2003 20:29:39 -0000 1.16
+++ reg_svr.pc 27 Jun 2005 09:15:11 -0000
@@ -42,6 +42,7 @@
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 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 @@
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;