]> code.citadel.org Git - citadel.git/blobdiff - citadel/user_ops.c
* Bump internal version number to 6.08
[citadel.git] / citadel / user_ops.c
index c6621951557fc57f6ffbea70a291eda2fa5c143f..a631c2cee2bb525c547206444b6089a294a036fa 100644 (file)
@@ -17,6 +17,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <pwd.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include "server.h"
 #include "database.h"
 #include "user_ops.h"
-#include "dynloader.h"
+#include "serv_extensions.h"
 #include "sysdep_decls.h"
 #include "support.h"
 #include "room_ops.h"
-#include "logging.h"
 #include "file_ops.h"
 #include "control.h"
 #include "msgbase.h"
 int getuser(struct usersupp *usbuf, char name[])
 {
 
-       char lowercase_name[32];
+       char lowercase_name[USERNAME_SIZE];
+       char sysuser_name[USERNAME_SIZE];
        int a;
        struct cdbdata *cdbus;
+       int using_sysuser = 0;
 
        memset(usbuf, 0, sizeof(struct usersupp));
-       for (a = 0; a <= strlen(name); ++a) {
-               if (a < sizeof(lowercase_name))
-                       lowercase_name[a] = tolower(name[a]);
+
+#ifdef ENABLE_AUTOLOGIN
+       if (CtdlAssociateSystemUser(sysuser_name, name) == 0) {
+               ++using_sysuser;
+       }
+#endif
+
+       if (using_sysuser) {
+               for (a = 0; a <= strlen(sysuser_name); ++a) {
+                       lowercase_name[a] = tolower(sysuser_name[a]);
+               }
+       }
+       else {
+               for (a = 0; a <= strlen(name); ++a) {
+                       if (a < sizeof(lowercase_name))
+                               lowercase_name[a] = tolower(name[a]);
+               }
        }
        lowercase_name[sizeof(lowercase_name) - 1] = 0;
 
        cdbus = cdb_fetch(CDB_USERSUPP, lowercase_name, strlen(lowercase_name));
-       if (cdbus == NULL) {
-               return (1);     /* user not found */
+       if (cdbus == NULL) {    /* user not found */
+               return(1);
        }
        memcpy(usbuf, cdbus->ptr,
               ((cdbus->len > sizeof(struct usersupp)) ?
@@ -105,7 +121,7 @@ int lgetuser(struct usersupp *usbuf, char *name)
  */
 void putuser(struct usersupp *usbuf)
 {
-       char lowercase_name[32];
+       char lowercase_name[USERNAME_SIZE];
        int a;
 
        for (a = 0; a <= strlen(usbuf->fullname); ++a) {
@@ -304,16 +320,36 @@ int getuserbynumber(struct usersupp *usbuf, long int number)
 }
 
 
+/*
+ * See if we can translate a system login name (i.e. from /etc/passwd)
+ * to a Citadel screen name.  Returns 0 if one is found.
+ */
+int CtdlAssociateSystemUser(char *screenname, char *loginname) {
+       struct passwd *p;
+       int a;
+
+       p = (struct passwd *) getpwnam(loginname);
+       if (p != NULL) {
+               strcpy(screenname, p->pw_gecos);
+               for (a = 0; a < strlen(screenname); ++a) {
+                       if (screenname[a] == ',') {
+                               screenname[a] = 0;
+                       }
+               }
+               return(0);
+       }
+       return(1);
+}
+
+
+
 /*
  * Back end for cmd_user() and its ilk
  */
 int CtdlLoginExistingUser(char *trythisname)
 {
        char username[SIZ];
-       char autoname[SIZ];
-       int found_user = 0;
-       struct passwd *p;
-       int a;
+       int found_user;
 
        if (trythisname == NULL) return login_not_found;
        safestrncpy(username, trythisname, sizeof username);
@@ -322,17 +358,9 @@ int CtdlLoginExistingUser(char *trythisname)
        if ((CC->logged_in)) {
                return login_already_logged_in;
        }
+
        found_user = getuser(&CC->usersupp, username);
-       if (found_user != 0) {
-               p = (struct passwd *) getpwnam(username);
-               if (p != NULL) {
-                       strcpy(autoname, p->pw_gecos);
-                       for (a = 0; a < strlen(autoname); ++a)
-                               if (autoname[a] == ',')
-                                       autoname[a] = 0;
-                       found_user = getuser(&CC->usersupp, autoname);
-               }
-       }
+
        if (found_user == 0) {
                if (((CC->nologin)) && (CC->usersupp.axlevel < 6)) {
                        return login_too_many_users;
@@ -388,11 +416,14 @@ void cmd_user(char *cmdbuf)
  */
 void session_startup(void)
 {
+       int i;
+
        syslog(LOG_NOTICE, "session %d: user <%s> logged in",
               CC->cs_pid, CC->curr_user);
 
        lgetuser(&CC->usersupp, CC->curr_user);
        ++(CC->usersupp.timescalled);
+       CC->previous_login = CC->usersupp.lastcall;
        time(&CC->usersupp.lastcall);
 
        /* If this user's name is the name of the system administrator
@@ -403,17 +434,30 @@ void session_startup(void)
        }
        lputuser(&CC->usersupp);
 
-       /* Run any startup routines registered by loadable modules */
-       PerformSessionHooks(EVT_LOGIN);
+       /*
+        * Populate CC->cs_inet_email with a default address.  This will be
+        * overwritten with the user's directory address, if one exists, when
+        * the vCard module's login hook runs.
+        */
+       snprintf(CC->cs_inet_email, sizeof CC->cs_inet_email, "%s@%s",
+               CC->usersupp.fullname, config.c_fqdn);
+       for (i=0; i<strlen(CC->cs_inet_email); ++i) {
+               if (isspace(CC->cs_inet_email[i])) {
+                       CC->cs_inet_email[i] = '_';
+               }
+       }
 
-       /* Create any personal rooms required by the system */
+       /* Create any personal rooms required by the system.
+        * (Technically, MAILROOM should be there already, but just in case...)
+        */
+       create_room(MAILROOM, 4, "", 0, 1, 0);
        create_room(SENTITEMS, 4, "", 0, 1, 0);
 
-       /* Enter the lobby */
-       usergoto(BASEROOM, 0, NULL, NULL);
+       /* Run any startup routines registered by loadable modules */
+       PerformSessionHooks(EVT_LOGIN);
 
-       /* Record this login in the Citadel log */
-       rec_log(CL_LOGIN, CC->curr_user);
+       /* Enter the lobby */
+       usergoto(config.c_baseroom, 0, 0, NULL, NULL);
 }
 
 
@@ -423,7 +467,7 @@ void logged_in_response(void)
                CIT_OK, CC->usersupp.fullname, CC->usersupp.axlevel,
                CC->usersupp.timescalled, CC->usersupp.posted,
                CC->usersupp.flags, CC->usersupp.usernum,
-               CC->usersupp.lastcall);
+               CC->previous_login);
 }
 
 
@@ -457,14 +501,6 @@ void logout(struct CitContext *who)
                network_talking_to(who->net_node, NTT_REMOVE);
        }
 
-       /*
-        * Yes, we really need to free EVERY LAST BYTE we allocated.
-        */
-       if (who->cs_inet_email != NULL) {
-               phree(who->cs_inet_email);
-               who->cs_inet_email = NULL;
-       }
-
        /* Do modular stuff... */
        PerformSessionHooks(EVT_LOGOUT);
 }
@@ -555,12 +591,18 @@ int CtdlTryPassword(char *password)
                return pass_wrong_password;
        }
        code = (-1);
-       if (CC->usersupp.uid == BBSUID) {
+
+
+#ifdef ENABLE_AUTOLOGIN
+       /* A uid of BBSUID or -1 indicates that this user exists only in
+        * Citadel, not in the underlying operating system.
+        */
+       if ( (CC->usersupp.uid == BBSUID) || (CC->usersupp.uid == (-1)) ) {
                strproc(password);
                strproc(CC->usersupp.password);
                code = strcasecmp(CC->usersupp.password, password);
        }
-#ifdef ENABLE_AUTOLOGIN
+       /* Any other uid means we have to check the system password database */
        else {
                if (validpw(CC->usersupp.uid, password)) {
                        code = 0;
@@ -570,13 +612,19 @@ int CtdlTryPassword(char *password)
                        lputuser(&CC->usersupp);
                }
        }
-#endif
+
+#else /* ENABLE_AUTOLOGIN */
+       strproc(password);
+       strproc(CC->usersupp.password);
+       code = strcasecmp(CC->usersupp.password, password);
+
+#endif /* ENABLE_AUTOLOGIN */
 
        if (!code) {
                do_login();
                return pass_ok;
        } else {
-               rec_log(CL_BADPW, CC->curr_user);
+               lprintf(3, "Bad password specified for <%s>\n", CC->curr_user);
                return pass_wrong_password;
        }
 }
@@ -618,7 +666,7 @@ int purge_user(char pname[])
 {
        char filename[64];
        struct usersupp usbuf;
-       char lowercase_name[32];
+       char lowercase_name[USERNAME_SIZE];
        int a;
        struct CitContext *ccptr;
        int user_is_logged_in = 0;
@@ -682,6 +730,7 @@ int purge_user(char pname[])
 int create_user(char *newusername, int become_user)
 {
        struct usersupp usbuf;
+       struct quickroom qrbuf;
        struct passwd *p = NULL;
        char username[SIZ];
        char mailboxname[ROOMNAMELEN];
@@ -692,13 +741,15 @@ int create_user(char *newusername, int become_user)
 
 #ifdef ENABLE_AUTOLOGIN
        p = (struct passwd *) getpwnam(username);
-#endif
        if (p != NULL) {
                extract_token(username, p->pw_gecos, 0, ',');
                uid = p->pw_uid;
        } else {
-               uid = BBSUID;
+               uid = (-1);
        }
+#else
+       uid = (-1);
+#endif
 
        if (!getuser(&usbuf, username)) {
                return (ERROR + ALREADY_EXISTS);
@@ -731,11 +782,19 @@ int create_user(char *newusername, int become_user)
        /* add user to userlog */
        putuser(&usbuf);
 
-       /* give the user a private mailbox and a configuration room */
+       /*
+        * Give the user a private mailbox and a configuration room.
+        * Make the latter an invisible system room.
+        */
        MailboxName(mailboxname, sizeof mailboxname, &usbuf, MAILROOM);
        create_room(mailboxname, 5, "", 0, 1, 1);
+
        MailboxName(mailboxname, sizeof mailboxname, &usbuf, USERCONFIGROOM);
        create_room(mailboxname, 5, "", 0, 1, 1);
+        if (lgetroom(&qrbuf, mailboxname) == 0) {
+                qrbuf.QRflags2 |= QR2_SYSTEM;
+                lputroom(&qrbuf);
+        }
 
        /* Everything below this line can be bypassed if administratively
           creating a user, instead of doing self-service account creation
@@ -751,10 +810,9 @@ int create_user(char *newusername, int become_user)
                if (getuser(&CC->usersupp, CC->curr_user)) {
                        return (ERROR + INTERNAL_ERROR);
                }
-       
-               rec_log(CL_NEWUSER, CC->curr_user);
        }
 
+       lprintf(3, "New user <%s> created\n", username);
        return (0);
 }
 
@@ -816,7 +874,6 @@ void cmd_newu(char *cmdbuf)
        } else {
                cprintf("%d unknown error\n", ERROR);
        }
-       rec_log(CL_NEWUSER, CC->curr_user);
 }
 
 
@@ -829,8 +886,7 @@ void cmd_setp(char *new_pw)
        if (CtdlAccessCheck(ac_logged_in)) {
                return;
        }
-
-       if (CC->usersupp.uid != BBSUID) {
+       if ( (CC->usersupp.uid != BBSUID) && (CC->usersupp.uid != (-1)) ) {
                cprintf("%d Not allowed.  Use the 'passwd' command.\n", ERROR);
                return;
        }
@@ -843,7 +899,7 @@ void cmd_setp(char *new_pw)
        strcpy(CC->usersupp.password, new_pw);
        lputuser(&CC->usersupp);
        cprintf("%d Password changed.\n", CIT_OK);
-       rec_log(CL_PWCHANGE, CC->curr_user);
+       lprintf(3, "Password changed for user <%s>\n", CC->curr_user);
        PerformSessionHooks(EVT_SETPASS);
 }
 
@@ -881,7 +937,6 @@ void cmd_creu(char *cmdbuf)
        } else {
                cprintf("%d An error occured creating the user account.\n", ERROR);
        }
-       rec_log(CL_NEWUSER, username);
 }
 
 
@@ -978,6 +1033,19 @@ void cmd_seen(char *argbuf) {
 }
 
 
+void cmd_gtsn(char *argbuf) {
+       char buf[SIZ];
+
+       if (CtdlAccessCheck(ac_logged_in)) {
+               return;
+       }
+
+       CtdlGetSeen(buf);
+       cprintf("%d %s\n", CIT_OK, buf);
+}
+
+
+
 /*
  * INVT and KICK commands
  */
@@ -995,14 +1063,20 @@ void cmd_invt_kick(char *iuser, int op)
        if (is_room_aide()
           || (atol(CC->quickroom.QRname) == CC->usersupp.usernum) ) {
                /* access granted */
-       }
-       else {
+       } else {
                /* access denied */
                 cprintf("%d Higher access or room ownership required.\n",
                         ERROR + HIGHER_ACCESS_REQUIRED);
                 return;
         }
 
+       if (!strncasecmp(CC->quickroom.QRname, config.c_baseroom,
+                        ROOMNAMELEN)) {
+               cprintf("%d Can't add/remove users from this room.\n",
+                       ERROR + NOT_HERE);
+               return;
+       }
+
        if (lgetuser(&USscratch, iuser) != 0) {
                cprintf("%d No such user.\n", ERROR);
                return;
@@ -1060,7 +1134,7 @@ int CtdlForgetThisRoom(void) {
        lputuser(&CC->usersupp);
 
        /* Return to the Lobby, so we don't end up in an undefined room */
-       usergoto(BASEROOM, 0, NULL, NULL);
+       usergoto(config.c_baseroom, 0, 0, NULL, NULL);
        return(0);
 
 }
@@ -1256,7 +1330,7 @@ void cmd_chek(void)
        /* check for mail */
        mail = InitialMailCheck();
 
-       cprintf("%d %d|%d|%d\n", CIT_OK, mail, regis, vali);
+       cprintf("%d %d|%d|%d|%s|\n", CIT_OK, mail, regis, vali, CC->cs_inet_email);
 }
 
 
@@ -1314,6 +1388,7 @@ void cmd_asup(char *cmdbuf)
 {
        struct usersupp usbuf;
        char requested_user[SIZ];
+       char notify[SIZ];
        int np;
        int newax;
        int deleted = 0;
@@ -1353,6 +1428,13 @@ void cmd_asup(char *cmdbuf)
                        deleted = 1;
                }
        }
+
+       if (deleted) {
+               sprintf(notify, "User <%s> deleted by %s\n",
+                       usbuf.fullname, CC->usersupp.fullname);
+               aide_message(notify);
+       }
+
        cprintf("%d Ok", CIT_OK);
        if (deleted)
                cprintf(" (%s deleted)", requested_user);