/*
- * CtdlGetUser() - retrieve named user into supplied buffer.
- * returns 0 on success
+ * CtdlGetUser() retrieve named user into supplied buffer.
+ * returns 0 on success
*/
-int CtdlGetUserLen(struct ctdluser *usbuf, const char *name, long len)
+int CtdlGetUser(struct ctdluser *usbuf, char *name)
{
-
char usernamekey[USERNAME_SIZE];
struct cdbdata *cdbus;
+ long len = cutuserkey(name);
if (usbuf != NULL) {
memset(usbuf, 0, sizeof(struct ctdluser));
return(1);
}
if (usbuf != NULL) {
- memcpy(usbuf, cdbus->ptr,
- ((cdbus->len > sizeof(struct ctdluser)) ?
- sizeof(struct ctdluser) : cdbus->len));
+ memcpy(usbuf, cdbus->ptr, ((cdbus->len > sizeof(struct ctdluser)) ? sizeof(struct ctdluser) : cdbus->len));
}
cdb_free(cdbus);
-
return (0);
}
-int CtdlGetUser(struct ctdluser *usbuf, char *name)
-{
- return CtdlGetUserLen(usbuf, name, cutuserkey(name));
-}
-
int CtdlLockGetCurrentUser(void)
{
CitContext *CCC = CC;
-
- return CtdlGetUserLen(&CCC->user, CCC->curr_user, cutuserkey(CCC->curr_user));
+ return CtdlGetUser(&CCC->user, CCC->curr_user);
}
+
/*
* CtdlGetUserLock() - same as getuser() but locks the record
*/
{
char usernamekey[USERNAME_SIZE];
- makeuserkey(usernamekey,
- usbuf->fullname,
- cutuserkey(usbuf->fullname));
-
+ makeuserkey(usernamekey, usbuf->fullname, cutuserkey(usbuf->fullname));
usbuf->version = REV_LEVEL;
- cdb_store(CDB_USERS,
- usernamekey, strlen(usernamekey),
- usbuf, sizeof(struct ctdluser));
-
+ cdb_store(CDB_USERS, usernamekey, strlen(usernamekey), usbuf, sizeof(struct ctdluser));
}
+
void CtdlPutCurrentUserLock()
{
CtdlPutUser(&CC->user);
}
-
/*
* rename_user() - this is tricky because the user's display name is the database key
*
syslog(LOG_DEBUG, "user_ops: can not rename user \"Citadel\".");
retcode = RENAMEUSER_NOT_FOUND;
} else {
- syslog(LOG_DEBUG, "user_ops: renaming <%s> to <%s>\n", oldname, newname);
+ syslog(LOG_DEBUG, "user_ops: renaming <%s> to <%s>", oldname, newname);
cdb_delete(CDB_USERS, oldnamekey, strlen(oldnamekey));
safestrncpy(usbuf.fullname, newname, sizeof usbuf.fullname);
CtdlPutUser(&usbuf);
}
-
/*
* Index-generating function used by Ctdl[Get|Set]Relationship
*/
struct ctdluser *rel_user,
struct ctdlroom *rel_room)
{
-
-
/* We don't use these in Citadel because they're implicit by the
* index, but they must be present if the database is exported.
*/
put_visit(newvisit);
}
+
/*
* Locate a relationship between a user and a room
*/
struct ctdluser *rel_user,
struct ctdlroom *rel_room)
{
-
char IndexBuf[32];
int IndexLen;
struct cdbdata *cdbvisit;
return(0);
}
+
/*
* Convenience function.
*/
{
if (CC->internal_pgm) return(0);
if (required_level >= ac_internal) {
- cprintf("%d This is not a user-level command.\n",
- ERROR + HIGHER_ACCESS_REQUIRED);
+ cprintf("%d This is not a user-level command.\n", ERROR + HIGHER_ACCESS_REQUIRED);
return(-1);
}
}
-
/*
* Is the user currently logged in an Admin?
*/
return (0);
}
- if ((CC->user.axlevel >= AxAideU)
- || (CC->room.QRroomaide == CC->user.usernum)) {
+ if ((CC->user.axlevel >= AxAideU) || (CC->room.QRroomaide == CC->user.usernum)) {
return (1);
} else {
return (0);
* getuserbyuid() - get user by system uid (for PAM mode authentication)
* returns 0 if user was found
*
- * WARNING: don't use this function unless you absolutely have to. It does
- * a sequential search and therefore is computationally expensive.
+ * WARNING: don't use this function unless you absolutely have to. It does
+ * a sequential search and therefore is computationally expensive.
+ *
+ * FIXME: build an index, dummy.
*/
int getuserbyuid(struct ctdluser *usbuf, uid_t number)
{
{
char username[SIZ];
int found_user;
- long len;
syslog(LOG_DEBUG, "user_ops: CtdlLoginExistingUser(%s, %s)", authname, trythisname);
/* Continue attempting user validation... */
safestrncpy(username, trythisname, sizeof (username));
striplt(username);
- len = cutuserkey(username);
if (IsEmptyStr(username)) {
return login_not_found;
* If not found, make one attempt to create it.
*/
found_user = getuserbyuid(&CC->user, pd.pw_uid);
- syslog(LOG_DEBUG, "user_ops: found it: uid=%ld, gecos=%s here: %d", (long)pd.pw_uid, pd.pw_gecos, found_user);
if (found_user != 0) {
- len = cutuserkey(username);
- create_user(username, len, 0);
+ create_user(username, CREATE_USER_DO_NOT_BECOME_USER, pd.pw_uid);
found_user = getuserbyuid(&CC->user, pd.pw_uid);
}
+ syslog(LOG_DEBUG, "user_ops: found it: uid=%ld, gecos=%s here: %d", (long)pd.pw_uid, pd.pw_gecos, found_user);
}
char ldap_cn[256];
char ldap_dn[256];
- found_user = CtdlTryUserLDAP(username, ldap_dn, sizeof ldap_dn, ldap_cn, sizeof ldap_cn, &ldap_uid, 0);
+ found_user = CtdlTryUserLDAP(username, ldap_dn, sizeof ldap_dn, ldap_cn, sizeof ldap_cn, &ldap_uid);
if (found_user != 0) {
return login_not_found;
}
found_user = getuserbyuid(&CC->user, ldap_uid);
if (found_user != 0) {
- create_user(username, len, 0);
+ create_user(ldap_cn, CREATE_USER_DO_NOT_BECOME_USER, ldap_uid);
found_user = getuserbyuid(&CC->user, ldap_uid);
}
if (((CC->nologin)) && (CC->user.axlevel < AxAideU)) {
return login_too_many_users;
} else {
- safestrncpy(CC->curr_user, CC->user.fullname,
- sizeof CC->curr_user);
+ safestrncpy(CC->curr_user, CC->user.fullname, sizeof CC->curr_user);
return login_ok;
}
}
}
}
+ /*
+ * If we are using LDAP authentication, extract the user's email addresses from the directory.
+ * FIXME make this a site configurable setting
+ */
+ #ifdef HAVE_LDAP
+ if ((CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP) || (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD)) {
+ char new_emailaddrs[512];
+ if (extract_email_addresses_from_ldap(CCC->ldap_dn, new_emailaddrs) == 0) {
+ strcpy(CCC->user.emailaddrs, new_emailaddrs);
+ }
+ }
+ #endif
+
+ /*
+ * No email address for user? Make one up.
+ */
+ if (IsEmptyStr(CCC->user.emailaddrs)) {
+ sprintf(CCC->user.emailaddrs, "cit%ld@%s", CCC->user.usernum, CtdlGetConfigStr("c_fqdn"));
+ }
+
CtdlPutUserLock(&CCC->user);
/*
- * Populate CCC->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.
+ * Populate cs_inet_email and cs_inet_other_emails with valid email addresses from the user record
*/
- snprintf(CCC->cs_inet_email, sizeof CCC->cs_inet_email, "%s@%s",
- CCC->user.fullname, CtdlGetConfigStr("c_fqdn"));
- convert_spaces_to_underscores(CCC->cs_inet_email);
+ strcpy(CCC->cs_inet_email, CCC->user.emailaddrs);
+ char *firstsep = strstr(CCC->cs_inet_email, "|");
+ if (firstsep) {
+ strcpy(CCC->cs_inet_other_emails, firstsep+1);
+ *firstsep = 0;
+ }
+ else {
+ CCC->cs_inet_other_emails[0] = 0;
+ }
/* Create any personal rooms required by the system.
* (Technically, MAILROOM should be there already, but just in case...)
begin_critical_section(S_CHKPWD);
rv = write(chkpwd_write_pipe[1], &uid, sizeof(uid_t));
if (rv == -1) {
- syslog(LOG_EMERG, "user_ops: communication with chkpwd broken: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: communication with chkpwd broken: %m");
end_critical_section(S_CHKPWD);
return 0;
}
rv = write(chkpwd_write_pipe[1], pass, 256);
if (rv == -1) {
- syslog(LOG_EMERG, "user_ops: communication with chkpwd broken: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: communication with chkpwd broken: %m");
end_critical_section(S_CHKPWD);
return 0;
}
rv = read(chkpwd_read_pipe[0], buf, 4);
if (rv == -1) {
- syslog(LOG_EMERG, "user_ops: ommunication with chkpwd broken: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: ommunication with chkpwd broken: %m");
end_critical_section(S_CHKPWD);
return 0;
}
syslog(LOG_DEBUG, "user_ops: starting chkpwd daemon for host authentication mode");
if ((stat(file_chkpwd, &filestats)==-1) || (filestats.st_size==0)) {
- printf("didn't find chkpwd daemon in %s: %s\n", file_chkpwd, strerror(errno));
+ syslog(LOG_ERR, "user_ops: %s: %m", file_chkpwd);
abort();
}
if (pipe(chkpwd_write_pipe) != 0) {
- syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %m");
abort();
}
if (pipe(chkpwd_read_pipe) != 0) {
- syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %m");
abort();
}
chkpwd_pid = fork();
if (chkpwd_pid < 0) {
- syslog(LOG_ERR, "user_ops: unable to fork chkpwd daemon: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: unable to fork chkpwd daemon: %m");
abort();
}
if (chkpwd_pid == 0) {
dup2(chkpwd_read_pipe[1], 1);
for (i=2; i<256; ++i) close(i);
execl(file_chkpwd, file_chkpwd, NULL);
- syslog(LOG_ERR, "user_ops: unable to exec chkpwd daemon: %s", strerror(errno));
+ syslog(LOG_ERR, "user_ops: unable to exec chkpwd daemon: %m");
abort();
exit(errno);
}
}
-int internal_create_user (const char *username, long len, struct ctdluser *usbuf, uid_t uid)
+int internal_create_user(char *username, struct ctdluser *usbuf, uid_t uid)
{
- if (!CtdlGetUserLen(usbuf, username, len)) {
+ if (!CtdlGetUser(usbuf, username)) {
return (ERROR + ALREADY_EXISTS);
}
* create_user() - back end processing to create a new user
*
* Set 'newusername' to the desired account name.
- * Set 'become_user' to nonzero if this is self-service account creation and we want
- * to actually log in as the user we just created, otherwise set it to 0.
+ * Set 'become_user' to CREATE_USER_BECOME_USER if this is self-service account creation and we want to
+ * actually log in as the user we just created, otherwise set it to CREATE_USER_DO_NOT_BECOME_USER
+ * Set 'uid' to some uid_t value to associate the account with an external auth user, or (-1) for native auth
*/
-int create_user(const char *newusername, long len, int become_user)
+int create_user(char *username, int become_user, uid_t uid)
{
struct ctdluser usbuf;
struct ctdlroom qrbuf;
- char username[256];
char mailboxname[ROOMNAMELEN];
char buf[SIZ];
int retval;
- uid_t uid = (-1);
-
- safestrncpy(username, newusername, sizeof username);
strproc(username);
-
-
- if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {
-
- /* host auth mode */
-
- struct passwd pd;
- struct passwd *tempPwdPtr;
- char pwdbuffer[SIZ];
-
-#ifdef HAVE_GETPWNAM_R
-#ifdef SOLARIS_GETPWUID
- tempPwdPtr = getpwnam_r(username, &pd, pwdbuffer, sizeof(pwdbuffer));
-#else // SOLARIS_GETPWUID
- getpwnam_r(username, &pd, pwdbuffer, sizeof pwdbuffer, &tempPwdPtr);
-#endif // SOLARIS_GETPWUID
-#else // HAVE_GETPWNAM_R
- tempPwdPtr = NULL;
-#endif // HAVE_GETPWNAM_R
- if (tempPwdPtr != NULL) {
- extract_token(username, pd.pw_gecos, 0, ',', sizeof username);
- uid = pd.pw_uid;
- if (IsEmptyStr (username))
- {
- safestrncpy(username, pd.pw_name, sizeof username);
- len = cutuserkey(username);
- }
- }
- else {
- return (ERROR + NO_SUCH_USER);
- }
+ if ((retval = internal_create_user(username, &usbuf, uid)) != 0) {
+ return retval;
}
-#ifdef HAVE_LDAP
- if ((CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP) || (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD)) {
- if (CtdlTryUserLDAP(username, NULL, 0, username, sizeof username, &uid, 0) != 0) {
- return(ERROR + NO_SUCH_USER);
- }
- }
-#endif /* HAVE_LDAP */
-
- if ((retval = internal_create_user(username, len, &usbuf, uid)) != 0)
- return retval;
-
/*
* Give the user a private mailbox and a configuration room.
* Make the latter an invisible system room.
* creating a user, instead of doing self-service account creation
*/
- if (become_user) {
+ if (become_user == CREATE_USER_BECOME_USER) {
/* Now become the user we just created */
memcpy(&CC->user, &usbuf, sizeof(struct ctdluser));
safestrncpy(CC->curr_user, username, sizeof CC->curr_user);