citadel
About: Citadel is an advanced messaging and collaboration system for groupware and BBS applications (preferred OS: Linux).
  Fossies Dox: citadel.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

user_ops.c
Go to the documentation of this file.
1/*
2 * Server functions which perform operations on user objects.
3 *
4 * Copyright (c) 1987-2020 by the citadel.org team
5 *
6 * This program is open source software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <stdlib.h>
16#include <unistd.h>
17#include "sysdep.h"
18#include <stdio.h>
19#include <sys/stat.h>
20#include <libcitadel.h>
21#include "control.h"
22#include "support.h"
23#include "citserver.h"
24#include "config.h"
25#include "citadel_ldap.h"
26#include "ctdl_module.h"
27#include "user_ops.h"
28#include "internet_addressing.h"
29
30/* These pipes are used to talk to the chkpwd daemon, which is forked during startup */
33
34
35/*
36 * makeuserkey() - convert a username into the format used as a database key
37 * "key" must be a buffer of at least USERNAME_SIZE
38 * (Key format is the username with all non-alphanumeric characters removed, and converted to lower case.)
39 */
40void makeuserkey(char *key, const char *username) {
41 int i;
42 int keylen = 0;
43
44 if (IsEmptyStr(username)) {
45 key[0] = 0;
46 return;
47 }
48
49 int len = strlen(username);
50 for (i=0; ((i<=len) && (i<USERNAME_SIZE-1)); ++i) {
51 if (isalnum((username[i]))) {
52 key[keylen++] = tolower(username[i]);
53 }
54 }
55 key[keylen++] = 0;
56}
57
58
59/*
60 * Compare two usernames to see if they are the same user after being keyed for the database
61 * Usage is identical to strcmp()
62 */
63int CtdlUserCmp(char *s1, char *s2) {
64 char k1[USERNAME_SIZE];
65 char k2[USERNAME_SIZE];
66
67 makeuserkey(k1, s1);
68 makeuserkey(k2, s2);
69 return(strcmp(k1,k2));
70}
71
72
73/*
74 * CtdlGetUser() retrieve named user into supplied buffer.
75 * returns 0 on success
76 */
77int CtdlGetUser(struct ctdluser *usbuf, char *name)
78{
79 char usernamekey[USERNAME_SIZE];
80 struct cdbdata *cdbus;
81
82 if (usbuf != NULL) {
83 memset(usbuf, 0, sizeof(struct ctdluser));
84 }
85
86 makeuserkey(usernamekey, name);
87 if (IsEmptyStr(usernamekey)) {
88 return(1); // empty user name
89 }
90 cdbus = cdb_fetch(CDB_USERS, usernamekey, strlen(usernamekey));
91
92 if (cdbus == NULL) { // user not found
93 return(1);
94 }
95 if (usbuf != NULL) {
96 memcpy(usbuf, cdbus->ptr, ((cdbus->len > sizeof(struct ctdluser)) ? sizeof(struct ctdluser) : cdbus->len));
97 }
98 cdb_free(cdbus);
99 return(0);
100}
101
102
104{
105 CitContext *CCC = CC;
106 return CtdlGetUser(&CCC->user, CCC->curr_user);
107}
108
109
110/*
111 * CtdlGetUserLock() - same as getuser() but locks the record
112 */
113int CtdlGetUserLock(struct ctdluser *usbuf, char *name)
114{
115 int retcode;
116
117 retcode = CtdlGetUser(usbuf, name);
118 if (retcode == 0) {
120 }
121 return(retcode);
122}
123
124
125/*
126 * CtdlPutUser() - write user buffer into the correct place on disk
127 */
129{
130 char usernamekey[USERNAME_SIZE];
131
132 makeuserkey(usernamekey, usbuf->fullname);
134 cdb_store(CDB_USERS, usernamekey, strlen(usernamekey), usbuf, sizeof(struct ctdluser));
135}
136
137
139{
140 CtdlPutUser(&CC->user);
141}
142
143
144/*
145 * CtdlPutUserLock() - same as putuser() but locks the record
146 */
148{
151}
152
153
154/*
155 * rename_user() - this is tricky because the user's display name is the database key
156 *
157 * Returns 0 on success or nonzero if there was an error...
158 *
159 */
160int rename_user(char *oldname, char *newname) {
161 int retcode = RENAMEUSER_OK;
162 struct ctdluser usbuf;
163
164 char oldnamekey[USERNAME_SIZE];
165 char newnamekey[USERNAME_SIZE];
166
167 /* Create the database keys... */
168 makeuserkey(oldnamekey, oldname);
169 makeuserkey(newnamekey, newname);
170
171 /* Lock up and get going */
173
174 /* We cannot rename a user who is currently logged in */
175 if (CtdlIsUserLoggedIn(oldname)) {
178 }
179
180 if (CtdlGetUser(&usbuf, newname) == 0) {
182 }
183 else {
184
185 if (CtdlGetUser(&usbuf, oldname) != 0) {
186 retcode = RENAMEUSER_NOT_FOUND;
187 }
188 else { /* Sanity checks succeeded. Now rename the user. */
189 if (usbuf.usernum == 0) {
190 syslog(LOG_DEBUG, "user_ops: can not rename user \"Citadel\".");
191 retcode = RENAMEUSER_NOT_FOUND;
192 } else {
193 syslog(LOG_DEBUG, "user_ops: renaming <%s> to <%s>", oldname, newname);
194 cdb_delete(CDB_USERS, oldnamekey, strlen(oldnamekey));
195 safestrncpy(usbuf.fullname, newname, sizeof usbuf.fullname);
197 cdb_store(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long), usbuf.fullname, strlen(usbuf.fullname)+1 );
198 retcode = RENAMEUSER_OK;
199 }
200 }
201
202 }
203
205 return(retcode);
206}
207
208
209/*
210 * Convert a username into the format used as a database key prior to version 928
211 * This only gets called by reindex_user_928()
212 */
213void makeuserkey_pre928(char *key, const char *username) {
214 int i;
215
216 int len = strlen(username);
217
218 if (len >= USERNAME_SIZE) {
219 syslog(LOG_INFO, "Username too long: %s", username);
220 len = USERNAME_SIZE - 1;
221 }
222 for (i=0; i<=len; ++i) {
223 key[i] = tolower(username[i]);
224 }
225}
226
227
228/*
229 * Read a user record using the pre-v928 index format, and write it back using the v928-and-higher index format.
230 * This ONLY gets called during an upgrade from version <928 to version >=928.
231 */
232void reindex_user_928(char *username, void *out_data) {
233
234 char oldkey[USERNAME_SIZE];
235 char newkey[USERNAME_SIZE];
236 struct cdbdata *cdbus;
237 struct ctdluser usbuf;
238
239 makeuserkey_pre928(oldkey, username);
240 makeuserkey(newkey, username);
241
242 syslog(LOG_DEBUG, "user_ops: reindex_user_928: %s <%s> --> <%s>", username, oldkey, newkey);
243
244 // Fetch the user record using the old index format
245 cdbus = cdb_fetch(CDB_USERS, oldkey, strlen(oldkey));
246 if (cdbus == NULL) {
247 syslog(LOG_INFO, "user_ops: <%s> not found, were they already reindexed?", username);
248 return;
249 }
250 memcpy(&usbuf, cdbus->ptr, ((cdbus->len > sizeof(struct ctdluser)) ? sizeof(struct ctdluser) : cdbus->len));
251 cdb_free(cdbus);
252
253 // delete the old record
254 cdb_delete(CDB_USERS, oldkey, strlen(oldkey));
255
256 // write the new record
257 cdb_store(CDB_USERS, newkey, strlen(newkey), &usbuf, sizeof(struct ctdluser));
258}
259
260
261/*
262 * Index-generating function used by Ctdl[Get|Set]Relationship
263 */
264int GenerateRelationshipIndex(char *IndexBuf,
265 long RoomID,
266 long RoomGen,
267 long UserID)
268{
269 struct {
270 long iRoomID;
271 long iRoomGen;
272 long iUserID;
273 } TheIndex;
274
275 TheIndex.iRoomID = RoomID;
276 TheIndex.iRoomGen = RoomGen;
277 TheIndex.iUserID = UserID;
278
279 memcpy(IndexBuf, &TheIndex, sizeof(TheIndex));
280 return(sizeof(TheIndex));
281}
282
283
284/*
285 * Back end for CtdlSetRelationship()
286 */
287void put_visit(visit *newvisit)
288{
289 char IndexBuf[32];
290 int IndexLen = 0;
291
292 memset (IndexBuf, 0, sizeof (IndexBuf));
293 /* Generate an index */
294 IndexLen = GenerateRelationshipIndex(IndexBuf, newvisit->v_roomnum, newvisit->v_roomgen, newvisit->v_usernum);
295
296 /* Store the record */
297 cdb_store(CDB_VISIT, IndexBuf, IndexLen,
298 newvisit, sizeof(visit)
299 );
300}
301
302
303/*
304 * Define a relationship between a user and a room
305 */
306void CtdlSetRelationship(visit *newvisit, struct ctdluser *rel_user, struct ctdlroom *rel_room) {
307 /* We don't use these in Citadel because they're implicit by the
308 * index, but they must be present if the database is exported.
309 */
310 newvisit->v_roomnum = rel_room->QRnumber;
311 newvisit->v_roomgen = rel_room->QRgen;
312 newvisit->v_usernum = rel_user->usernum;
313
314 put_visit(newvisit);
315}
316
317
318/*
319 * Locate a relationship between a user and a room
320 */
321void CtdlGetRelationship(visit *vbuf, struct ctdluser *rel_user, struct ctdlroom *rel_room) {
322 char IndexBuf[32];
323 int IndexLen;
324 struct cdbdata *cdbvisit;
325
326 /* Generate an index */
327 IndexLen = GenerateRelationshipIndex(IndexBuf, rel_room->QRnumber, rel_room->QRgen, rel_user->usernum);
328
329 /* Clear out the buffer */
330 memset(vbuf, 0, sizeof(visit));
331
332 cdbvisit = cdb_fetch(CDB_VISIT, IndexBuf, IndexLen);
333 if (cdbvisit != NULL) {
334 memcpy(vbuf, cdbvisit->ptr, ((cdbvisit->len > sizeof(visit)) ? sizeof(visit) : cdbvisit->len));
335 cdb_free(cdbvisit);
336 }
337 else {
338 /* If this is the first time the user has seen this room,
339 * set the view to be the default for the room.
340 */
341 vbuf->v_view = rel_room->QRdefaultview;
342 }
343
344 /* Set v_seen if necessary */
345 if (vbuf->v_seen[0] == 0) {
346 snprintf(vbuf->v_seen, sizeof vbuf->v_seen, "*:%ld", vbuf->v_lastseen);
347 }
348}
349
350
351void CtdlMailboxName(char *buf, size_t n, const struct ctdluser *who, const char *prefix)
352{
353 snprintf(buf, n, "%010ld.%s", who->usernum, prefix);
354}
355
356
357void MailboxName(char *buf, size_t n, const struct ctdluser *who, const char *prefix)
358{
359 snprintf(buf, n, "%010ld.%s", who->usernum, prefix);
360}
361
362
363/*
364 * Check to see if the specified user has Internet mail permission
365 * (returns nonzero if permission is granted)
366 */
368
369 /* Do not allow twits to send Internet mail */
370 if (who->axlevel <= AxProbU) return(0);
371
372 /* Globally enabled? */
373 if (CtdlGetConfigInt("c_restrict") == 0) return(1);
374
375 /* User flagged ok? */
376 if (who->flags & US_INTERNET) return(2);
377
378 /* Admin level access? */
379 if (who->axlevel >= AxAideU) return(3);
380
381 /* No mail for you! */
382 return(0);
383}
384
385
386/*
387 * Convenience function.
388 */
389int CtdlAccessCheck(int required_level)
390{
391 if (CC->internal_pgm) return(0);
392 if (required_level >= ac_internal) {
393 cprintf("%d This is not a user-level command.\n", ERROR + HIGHER_ACCESS_REQUIRED);
394 return(-1);
395 }
396
397 if ((required_level >= ac_logged_in_or_guest) && (CC->logged_in == 0) && (CtdlGetConfigInt("c_guest_logins") == 0)) {
398 cprintf("%d Not logged in.\n", ERROR + NOT_LOGGED_IN);
399 return(-1);
400 }
401
402 if ((required_level >= ac_logged_in) && (CC->logged_in == 0)) {
403 cprintf("%d Not logged in.\n", ERROR + NOT_LOGGED_IN);
404 return(-1);
405 }
406
407 if (CC->user.axlevel >= AxAideU) return(0);
408 if (required_level >= ac_aide) {
409 cprintf("%d This command requires Admin access.\n",
411 return(-1);
412 }
413
414 if (is_room_aide()) return(0);
415 if (required_level >= ac_room_aide) {
416 cprintf("%d This command requires Admin or Room Admin access.\n",
418 return(-1);
419 }
420
421 /* shhh ... succeed quietly */
422 return(0);
423}
424
425
426/*
427 * Is the user currently logged in an Admin?
428 */
429int is_aide(void)
430{
431 if (CC->user.axlevel >= AxAideU)
432 return(1);
433 else
434 return(0);
435}
436
437
438/*
439 * Is the user currently logged in an Admin *or* the room Admin for this room?
440 */
442{
443
444 if (!CC->logged_in) {
445 return(0);
446 }
447
448 if ((CC->user.axlevel >= AxAideU) || (CC->room.QRroomaide == CC->user.usernum)) {
449 return(1);
450 } else {
451 return(0);
452 }
453}
454
455
456/*
457 * CtdlGetUserByNumber() - get user by number
458 * returns 0 if user was found
459 *
460 * Note: fetching a user this way requires one additional database operation.
461 */
462int CtdlGetUserByNumber(struct ctdluser *usbuf, long number)
463{
464 struct cdbdata *cdbun;
465 int r;
466
467 cdbun = cdb_fetch(CDB_USERSBYNUMBER, &number, sizeof(long));
468 if (cdbun == NULL) {
469 syslog(LOG_INFO, "user_ops: %ld not found", number);
470 return(-1);
471 }
472
473 syslog(LOG_INFO, "user_ops: %ld maps to %s", number, cdbun->ptr);
474 r = CtdlGetUser(usbuf, cdbun->ptr);
475 cdb_free(cdbun);
476 return(r);
477}
478
479
480/*
481 * Helper function for rebuild_usersbynumber()
482 */
483void rebuild_ubn_for_user(char *username, void *data) {
484 struct ctdluser u;
485
486 syslog(LOG_DEBUG, "user_ops: rebuilding usersbynumber index for %s", username);
487 if (CtdlGetUser(&u, username) == 0) {
488 cdb_store(CDB_USERSBYNUMBER, &(u.usernum), sizeof(long), u.fullname, strlen(u.fullname)+1);
489 }
490}
491
492
493/*
494 * Rebuild the users-by-number index
495 */
497 cdb_trunc(CDB_USERSBYNUMBER); /* delete the old indices */
498 ForEachUser(rebuild_ubn_for_user, NULL); /* enumerate the users */
499}
500
501
502/*
503 * getuserbyuid() Get user by system uid (for PAM mode authentication)
504 * Returns 0 if user was found
505 * This now uses an extauth index.
506 */
507int getuserbyuid(struct ctdluser *usbuf, uid_t number)
508{
509 struct cdbdata *cdbextauth;
510 long usernum = 0;
511 StrBuf *claimed_id;
512
513 claimed_id = NewStrBuf();
514 StrBufPrintf(claimed_id, "uid:%d", number);
515 cdbextauth = cdb_fetch(CDB_EXTAUTH, ChrPtr(claimed_id), StrLength(claimed_id));
516 FreeStrBuf(&claimed_id);
517 if (cdbextauth == NULL) {
518 return(-1);
519 }
520
521 memcpy(&usernum, cdbextauth->ptr, sizeof(long));
522 cdb_free(cdbextauth);
523
524 if (!CtdlGetUserByNumber(usbuf, usernum)) {
525 return(0);
526 }
527
528 return(-1);
529}
530
531
532/*
533 * Back end for cmd_user() and its ilk
534 */
535int CtdlLoginExistingUser(const char *trythisname)
536{
537 char username[SIZ];
538 int found_user;
539
540 syslog(LOG_DEBUG, "user_ops: CtdlLoginExistingUser(%s)", trythisname);
541
542 if ((CC->logged_in)) {
544 }
545
546 if (trythisname == NULL) return login_not_found;
547
548 if (!strncasecmp(trythisname, "SYS_", 4))
549 {
550 syslog(LOG_DEBUG, "user_ops: system user \"%s\" is not allowed to log in.", trythisname);
551 return login_not_found;
552 }
553
554 /* Continue attempting user validation... */
555 safestrncpy(username, trythisname, sizeof (username));
556 striplt(username);
557
558 if (IsEmptyStr(username)) {
559 return login_not_found;
560 }
561
562 if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {
563
564 /* host auth mode */
565
566 struct passwd pd;
567 struct passwd *tempPwdPtr;
568 char pwdbuffer[256];
569
570 syslog(LOG_DEBUG, "user_ops: asking host about <%s>", username);
571#ifdef HAVE_GETPWNAM_R
572#ifdef SOLARIS_GETPWUID
573 syslog(LOG_DEBUG, "user_ops: calling getpwnam_r()");
574 tempPwdPtr = getpwnam_r(username, &pd, pwdbuffer, sizeof pwdbuffer);
575#else // SOLARIS_GETPWUID
576 syslog(LOG_DEBUG, "user_ops: calling getpwnam_r()");
577 getpwnam_r(username, &pd, pwdbuffer, sizeof pwdbuffer, &tempPwdPtr);
578#endif // SOLARIS_GETPWUID
579#else // HAVE_GETPWNAM_R
580 syslog(LOG_DEBUG, "user_ops: SHOULD NEVER GET HERE!!!");
581 tempPwdPtr = NULL;
582#endif // HAVE_GETPWNAM_R
583 if (tempPwdPtr == NULL) {
584 syslog(LOG_DEBUG, "user_ops: no such user <%s>", username);
585 return login_not_found;
586 }
587
588 /* Locate the associated Citadel account. If not found, make one attempt to create it. */
589 found_user = getuserbyuid(&CC->user, pd.pw_uid);
590 if (found_user != 0) {
591 create_user(username, CREATE_USER_DO_NOT_BECOME_USER, pd.pw_uid);
592 found_user = getuserbyuid(&CC->user, pd.pw_uid);
593 }
594 syslog(LOG_DEBUG, "user_ops: found it: uid=%ld, gecos=%s here: %d", (long)pd.pw_uid, pd.pw_gecos, found_user);
595
596 }
597
598#ifdef HAVE_LDAP
599 else if ((CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP) || (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD)) {
600
601 /* LDAP auth mode */
602
603 uid_t ldap_uid;
604 char ldap_cn[256];
605 char ldap_dn[256];
606
607 found_user = CtdlTryUserLDAP(username, ldap_dn, sizeof ldap_dn, ldap_cn, sizeof ldap_cn, &ldap_uid);
608 if (found_user != 0) {
609 return login_not_found;
610 }
611
612 found_user = getuserbyuid(&CC->user, ldap_uid);
613 if (found_user != 0) {
615 found_user = getuserbyuid(&CC->user, ldap_uid);
616 }
617
618 if (found_user == 0) {
619 if (CC->ldap_dn != NULL) free(CC->ldap_dn);
620 CC->ldap_dn = strdup(ldap_dn);
621 }
622
623 }
624#endif
625
626 else {
627 /* native auth mode */
628
629 struct recptypes *valid = NULL;
630
631 /* First, try to log in as if the supplied name is a display name */
632 found_user = CtdlGetUser(&CC->user, username);
633
634 /* If that didn't work, try to log in as if the supplied name * is an e-mail address */
635 if (found_user != 0) {
636 valid = validate_recipients(username, NULL, 0);
637 if (valid != NULL) {
638 if (valid->num_local == 1) {
639 found_user = CtdlGetUser(&CC->user, valid->recp_local);
640 }
641 free_recipients(valid);
642 }
643 }
644 }
645
646 /* Did we find something? */
647 if (found_user == 0) {
648 if (((CC->nologin)) && (CC->user.axlevel < AxAideU)) {
650 } else {
651 safestrncpy(CC->curr_user, CC->user.fullname, sizeof CC->curr_user);
652 return login_ok;
653 }
654 }
655 return login_not_found;
656}
657
658
659/*
660 * session startup code which is common to both cmd_pass() and cmd_newu()
661 */
662void do_login(void)
663{
664 CC->logged_in = 1;
665 syslog(LOG_NOTICE, "user_ops: <%s> logged in", CC->curr_user);
666
667 CtdlGetUserLock(&CC->user, CC->curr_user);
668 ++(CC->user.timescalled);
669 CC->previous_login = CC->user.lastcall;
670 time(&CC->user.lastcall);
671
672 /* If this user's name is the name of the system administrator
673 * (as specified in setup), automatically assign access level 6.
674 */
675 if ( (!IsEmptyStr(CtdlGetConfigStr("c_sysadm"))) && (!strcasecmp(CC->user.fullname, CtdlGetConfigStr("c_sysadm"))) ) {
676 CC->user.axlevel = AxAideU;
677 }
678
679 /* If we're authenticating off the host system, automatically give root the highest level of access. */
680 if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {
681 if (CC->user.uid == 0) {
682 CC->user.axlevel = AxAideU;
683 }
684 }
685 CtdlPutUserLock(&CC->user);
686
687 /* If we are using LDAP authentication, extract the user's email addresses from the directory. */
688#ifdef HAVE_LDAP
689 if ((CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP) || (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD)) {
690 char new_emailaddrs[512];
691 if (CtdlGetConfigInt("c_ldap_sync_email_addrs") > 0) {
692 if (extract_email_addresses_from_ldap(CC->ldap_dn, new_emailaddrs) == 0) {
693 CtdlSetEmailAddressesForUser(CC->user.fullname, new_emailaddrs);
694 }
695 }
696 }
697#endif
698
699 /* If the user does not have any email addresses assigned, generate one. */
700 if (IsEmptyStr(CC->user.emailaddrs)) {
702 }
703
704 /* Populate the user principal identity, which is consistent and never aliased */
705 strcpy(CC->cs_principal_id, "");
706 makeuserkey(CC->cs_principal_id, CC->user.fullname);
707 strcat(CC->cs_principal_id, "@");
708 strcat(CC->cs_principal_id, CtdlGetConfigStr("c_fqdn"));
709
710 /*
711 * Populate cs_inet_email and cs_inet_other_emails with valid email addresses from the user record
712 */
713 strcpy(CC->cs_inet_email, CC->user.emailaddrs);
714 char *firstsep = strstr(CC->cs_inet_email, "|");
715 if (firstsep) {
716 strcpy(CC->cs_inet_other_emails, firstsep+1);
717 *firstsep = 0;
718 }
719 else {
720 CC->cs_inet_other_emails[0] = 0;
721 }
722
723 /* Create any personal rooms required by the system.
724 * (Technically, MAILROOM should be there already, but just in case...)
725 */
726 CtdlCreateRoom(MAILROOM, 4, "", 0, 1, 0, VIEW_MAILBOX);
727 CtdlCreateRoom(SENTITEMS, 4, "", 0, 1, 0, VIEW_MAILBOX);
728 CtdlCreateRoom(USERTRASHROOM, 4, "", 0, 1, 0, VIEW_MAILBOX);
729 CtdlCreateRoom(USERDRAFTROOM, 4, "", 0, 1, 0, VIEW_MAILBOX);
730
731 /* Run any startup routines registered by loadable modules */
733
734 /* Enter the lobby */
735 CtdlUserGoto(CtdlGetConfigStr("c_baseroom"), 0, 0, NULL, NULL, NULL, NULL);
736}
737
738
740{
741 cprintf("%d %s|%d|%ld|%ld|%u|%ld|%ld\n",
742 CIT_OK, CC->user.fullname, CC->user.axlevel,
743 CC->user.timescalled, CC->user.posted,
744 CC->user.flags, CC->user.usernum,
745 CC->previous_login
746 );
747}
748
749
751{
752 CitContext *CCC = MyContext();
753
754 syslog(LOG_DEBUG, "user_ops: CtdlUserLogout() logging out <%s> from session %d", CCC->curr_user, CCC->cs_pid);
755
756 /* Run any hooks registered by modules... */
758
759 /*
760 * Clear out some session data. Most likely, the CitContext for this
761 * session is about to get nuked when the session disconnects, but
762 * since it's possible to log in again without reconnecting, we cannot
763 * make that assumption.
764 */
765 CCC->logged_in = 0;
766
767 /* Check to see if the user was deleted while logged in and purge them if necessary */
768 if ((CCC->user.axlevel == AxDeleted) && (CCC->user.usernum)) {
770 }
771
772 /* Clear out the user record in memory so we don't behave like a ghost */
773 memset(&CCC->user, 0, sizeof(struct ctdluser));
774 CCC->curr_user[0] = 0;
775 CCC->cs_inet_email[0] = 0;
776 CCC->cs_inet_other_emails[0] = 0;
777 CCC->cs_inet_fn[0] = 0;
778
779 /* Free any output buffers */
781}
782
783
784/*
785 * Validate a password on the host unix system by talking to the chkpwd daemon
786 */
787static int validpw(uid_t uid, const char *pass)
788{
789 char buf[256];
790 int rv = 0;
791
792 if (IsEmptyStr(pass)) {
793 syslog(LOG_DEBUG, "user_ops: refusing to chkpwd for uid=%d with empty password", uid);
794 return 0;
795 }
796
797 syslog(LOG_DEBUG, "user_ops: validating password for uid=%d using chkpwd...", uid);
798
800 rv = write(chkpwd_write_pipe[1], &uid, sizeof(uid_t));
801 if (rv == -1) {
802 syslog(LOG_ERR, "user_ops: communication with chkpwd broken: %m");
804 return 0;
805 }
806 rv = write(chkpwd_write_pipe[1], pass, 256);
807 if (rv == -1) {
808 syslog(LOG_ERR, "user_ops: communication with chkpwd broken: %m");
810 return 0;
811 }
812 rv = read(chkpwd_read_pipe[0], buf, 4);
813 if (rv == -1) {
814 syslog(LOG_ERR, "user_ops: ommunication with chkpwd broken: %m");
816 return 0;
817 }
819
820 if (!strncmp(buf, "PASS", 4)) {
821 syslog(LOG_DEBUG, "user_ops: chkpwd pass");
822 return(1);
823 }
824
825 syslog(LOG_DEBUG, "user_ops: chkpwd fail");
826 return 0;
827}
828
829
830/*
831 * Start up the chkpwd daemon so validpw() has something to talk to
832 */
834 pid_t chkpwd_pid;
835 struct stat filestats;
836 int i;
837
838 syslog(LOG_DEBUG, "user_ops: starting chkpwd daemon for host authentication mode");
839
840 if ((stat(file_chkpwd, &filestats)==-1) || (filestats.st_size==0)) {
841 syslog(LOG_ERR, "user_ops: %s: %m", file_chkpwd);
842 abort();
843 }
844 if (pipe(chkpwd_write_pipe) != 0) {
845 syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %m");
846 abort();
847 }
848 if (pipe(chkpwd_read_pipe) != 0) {
849 syslog(LOG_ERR, "user_ops: unable to create pipe for chkpwd daemon: %m");
850 abort();
851 }
852
853 chkpwd_pid = fork();
854 if (chkpwd_pid < 0) {
855 syslog(LOG_ERR, "user_ops: unable to fork chkpwd daemon: %m");
856 abort();
857 }
858 if (chkpwd_pid == 0) {
859 dup2(chkpwd_write_pipe[0], 0);
860 dup2(chkpwd_read_pipe[1], 1);
861 for (i=2; i<256; ++i) close(i);
862 execl(file_chkpwd, file_chkpwd, NULL);
863 syslog(LOG_ERR, "user_ops: unable to exec chkpwd daemon: %m");
864 abort();
865 exit(errno);
866 }
867}
868
869
870int CtdlTryPassword(const char *password, long len)
871{
872 int code;
873 CitContext *CCC = CC;
874
875 if ((CCC->logged_in)) {
876 syslog(LOG_WARNING, "user_ops: CtdlTryPassword: already logged in");
878 }
879 if (!strcmp(CCC->curr_user, NLI)) {
880 syslog(LOG_WARNING, "user_ops: CtdlTryPassword: no user selected");
881 return pass_no_user;
882 }
883 if (CtdlGetUser(&CCC->user, CCC->curr_user)) {
884 syslog(LOG_ERR, "user_ops: CtdlTryPassword: internal error");
885 return pass_internal_error;
886 }
887 if (password == NULL) {
888 syslog(LOG_INFO, "user_ops: CtdlTryPassword: NULL password string supplied");
889 return pass_wrong_password;
890 }
891
892 else if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {
893
894 /* host auth mode */
895
896 if (validpw(CCC->user.uid, password)) {
897 code = 0;
898
899 /*
900 * sooper-seekrit hack: populate the password field in the
901 * citadel database with the password that the user typed,
902 * if it's correct. This allows most sites to convert from
903 * host auth to native auth if they want to. If you think
904 * this is a security hazard, comment it out.
905 */
906
907 CtdlGetUserLock(&CCC->user, CCC->curr_user);
908 safestrncpy(CCC->user.password, password, sizeof CCC->user.password);
909 CtdlPutUserLock(&CCC->user);
910
911 /*
912 * (sooper-seekrit hack ends here)
913 */
914 }
915 else {
916 code = (-1);
917 }
918 }
919
920#ifdef HAVE_LDAP
921 else if ((CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP) || (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD)) {
922
923 /* LDAP auth mode */
924
925 if ((CCC->ldap_dn) && (!CtdlTryPasswordLDAP(CCC->ldap_dn, password))) {
926 code = 0;
927 }
928 else {
929 code = (-1);
930 }
931 }
932#endif
933
934 else {
935
936 /* native auth mode */
937 char *pw;
938
939 pw = (char*) malloc(len + 1);
940 memcpy(pw, password, len + 1);
941 strproc(pw);
942 strproc(CCC->user.password);
943 code = strcasecmp(CCC->user.password, pw);
944 if (code != 0) {
945 strproc(pw);
946 strproc(CCC->user.password);
947 code = strcasecmp(CCC->user.password, pw);
948 }
949 free (pw);
950 }
951
952 if (!code) {
953 do_login();
954 return pass_ok;
955 }
956 else {
957 syslog(LOG_WARNING, "user_ops: bad password specified for <%s> Service <%s> Port <%ld> Remote <%s / %s>",
958 CCC->curr_user,
959 CCC->ServiceName,
960 CCC->tcp_port,
961 CCC->cs_host,
962 CCC->cs_addr
963 );
964 return pass_wrong_password;
965 }
966}
967
968
969/*
970 * Delete a user record *and* all of its related resources.
971 */
972int purge_user(char pname[])
973{
974 struct ctdluser usbuf;
975 char usernamekey[USERNAME_SIZE];
976
977 makeuserkey(usernamekey, pname);
978
979 /* If the name is empty we can't find them in the DB any way so just return */
980 if (IsEmptyStr(pname)) {
981 return(ERROR + NO_SUCH_USER);
982 }
983
984 if (CtdlGetUser(&usbuf, pname) != 0) {
985 syslog(LOG_ERR, "user_ops: cannot purge user <%s> - not found", pname);
986 return(ERROR + NO_SUCH_USER);
987 }
988
989 /* Don't delete a user who is currently logged in. Instead, just
990 * set the access level to 0, and let the account get swept up
991 * during the next purge.
992 */
994 syslog(LOG_WARNING, "user_ops: <%s> is logged in; not deleting", pname);
995 usbuf.axlevel = AxDeleted;
997 return(1);
998 }
999
1000 syslog(LOG_NOTICE, "user_ops: deleting <%s>", pname);
1001
1002 /* Perform any purge functions registered by server extensions */
1004
1005 /* delete any existing user/room relationships */
1006 cdb_delete(CDB_VISIT, &usbuf.usernum, sizeof(long));
1007
1008 /* delete the users-by-number index record */
1009 cdb_delete(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long));
1010
1011 /* delete the userlog entry */
1012 cdb_delete(CDB_USERS, usernamekey, strlen(usernamekey));
1013
1014 return(0);
1015}
1016
1017
1018int internal_create_user(char *username, struct ctdluser *usbuf, uid_t uid)
1019{
1020 if (!CtdlGetUser(usbuf, username)) {
1021 return(ERROR + ALREADY_EXISTS);
1022 }
1023
1024 /* Go ahead and initialize a new user record */
1025 memset(usbuf, 0, sizeof(struct ctdluser));
1026 safestrncpy(usbuf->fullname, username, sizeof usbuf->fullname);
1027 strcpy(usbuf->password, "");
1028 usbuf->uid = uid;
1029
1030 /* These are the default flags on new accounts */
1032
1033 usbuf->timescalled = 0;
1034 usbuf->posted = 0;
1035 usbuf->axlevel = CtdlGetConfigInt("c_initax");
1036 usbuf->lastcall = time(NULL);
1037
1038 /* fetch a new user number */
1040
1041 /* add user to the database */
1043 cdb_store(CDB_USERSBYNUMBER, &usbuf->usernum, sizeof(long), usbuf->fullname, strlen(usbuf->fullname)+1);
1044
1045 /* If non-native auth, index by uid */
1046 if ((usbuf->uid > 0) && (usbuf->uid != NATIVE_AUTH_UID)) {
1047 StrBuf *claimed_id = NewStrBuf();
1048 StrBufPrintf(claimed_id, "uid:%d", usbuf->uid);
1049 attach_extauth(usbuf, claimed_id);
1050 FreeStrBuf(&claimed_id);
1051 }
1052
1053 return(0);
1054}
1055
1056
1057/*
1058 * create_user() - back end processing to create a new user
1059 *
1060 * Set 'newusername' to the desired account name.
1061 * Set 'become_user' to CREATE_USER_BECOME_USER if this is self-service account creation and we want to
1062 * actually log in as the user we just created, otherwise set it to CREATE_USER_DO_NOT_BECOME_USER
1063 * Set 'uid' to some uid_t value to associate the account with an external auth user, or (-1) for native auth
1064 */
1065int create_user(char *username, int become_user, uid_t uid)
1066{
1067 struct ctdluser usbuf;
1068 struct ctdlroom qrbuf;
1069 char mailboxname[ROOMNAMELEN];
1070 char buf[SIZ];
1071 int retval;
1072
1073 strproc(username);
1074 if ((retval = internal_create_user(username, &usbuf, uid)) != 0) {
1075 return retval;
1076 }
1077
1078 /*
1079 * Give the user a private mailbox and a configuration room.
1080 * Make the latter an invisible system room.
1081 */
1082 CtdlMailboxName(mailboxname, sizeof mailboxname, &usbuf, MAILROOM);
1083 CtdlCreateRoom(mailboxname, 5, "", 0, 1, 1, VIEW_MAILBOX);
1084
1085 CtdlMailboxName(mailboxname, sizeof mailboxname, &usbuf, USERCONFIGROOM);
1086 CtdlCreateRoom(mailboxname, 5, "", 0, 1, 1, VIEW_BBS);
1087 if (CtdlGetRoomLock(&qrbuf, mailboxname) == 0) {
1090 }
1091
1092 /* Perform any create functions registered by server extensions */
1094
1095 /* Everything below this line can be bypassed if administratively
1096 * creating a user, instead of doing self-service account creation
1097 */
1098
1099 if (become_user == CREATE_USER_BECOME_USER) {
1100 /* Now become the user we just created */
1101 memcpy(&CC->user, &usbuf, sizeof(struct ctdluser));
1102 safestrncpy(CC->curr_user, username, sizeof CC->curr_user);
1103 do_login();
1104
1105 /* Check to make sure we're still who we think we are */
1106 if (CtdlGetUser(&CC->user, CC->curr_user)) {
1107 return(ERROR + INTERNAL_ERROR);
1108 }
1109 }
1110
1111 snprintf(buf, SIZ,
1112 "New user account <%s> has been created, from host %s [%s].\n",
1113 username,
1114 CC->cs_host,
1115 CC->cs_addr
1116 );
1117 CtdlAideMessage(buf, "User Creation Notice");
1118 syslog(LOG_NOTICE, "user_ops: <%s> created", username);
1119 return(0);
1120}
1121
1122
1123/*
1124 * set password - back end api code
1125 */
1126void CtdlSetPassword(char *new_pw)
1127{
1128 CtdlGetUserLock(&CC->user, CC->curr_user);
1129 safestrncpy(CC->user.password, new_pw, sizeof(CC->user.password));
1130 CtdlPutUserLock(&CC->user);
1131 syslog(LOG_INFO, "user_ops: password changed for <%s>", CC->curr_user);
1133}
1134
1135
1136/*
1137 * API function for cmd_invt_kick() and anything else that needs to
1138 * invite or kick out a user to/from a room.
1139 *
1140 * Set iuser to the name of the user, and op to 1=invite or 0=kick
1141 */
1142int CtdlInvtKick(char *iuser, int op) {
1143 struct ctdluser USscratch;
1144 visit vbuf;
1145 char bbb[SIZ];
1146
1147 if (CtdlGetUser(&USscratch, iuser) != 0) {
1148 return(1);
1149 }
1150
1151 CtdlGetRelationship(&vbuf, &USscratch, &CC->room);
1152 if (op == 1) {
1153 vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
1155 }
1156 if (op == 0) {
1157 vbuf.v_flags = vbuf.v_flags & ~V_ACCESS;
1159 }
1160 CtdlSetRelationship(&vbuf, &USscratch, &CC->room);
1161
1162 /* post a message in Aide> saying what we just did */
1163 snprintf(bbb, sizeof bbb, "%s has been %s \"%s\" by %s.\n",
1164 iuser,
1165 ((op == 1) ? "invited to" : "kicked out of"),
1166 CC->room.QRname,
1167 (CC->logged_in ? CC->user.fullname : "an administrator")
1168 );
1169 CtdlAideMessage(bbb,"User Admin Message");
1170 return(0);
1171}
1172
1173
1174/*
1175 * Forget (Zap) the current room (API call)
1176 * Returns 0 on success
1177 */
1179 visit vbuf;
1180
1181 /* On some systems, Admins are not allowed to forget rooms */
1182 if (is_aide() && (CtdlGetConfigInt("c_aide_zap") == 0)
1183 && ((CC->room.QRflags & QR_MAILBOX) == 0) ) {
1184 return(1);
1185 }
1186
1187 CtdlGetUserLock(&CC->user, CC->curr_user);
1188 CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
1189
1191 vbuf.v_flags = vbuf.v_flags & ~V_ACCESS;
1192
1193 CtdlSetRelationship(&vbuf, &CC->user, &CC->room);
1194 CtdlPutUserLock(&CC->user);
1195
1196 /* Return to the Lobby, so we don't end up in an undefined room */
1197 CtdlUserGoto(CtdlGetConfigStr("c_baseroom"), 0, 0, NULL, NULL, NULL, NULL);
1198 return(0);
1199}
1200
1201
1202/*
1203 * Traverse the user file and perform a callback for each user record.
1204 * (New improved version that runs in two phases so that callbacks can perform writes without having a r/o cursor open)
1205 */
1206void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data)
1207{
1208 struct cdbdata *cdbus;
1209 struct ctdluser *usptr;
1210
1211 struct feu {
1212 struct feu *next;
1213 char username[USERNAME_SIZE];
1214 };
1215 struct feu *ufirst = NULL;
1216 struct feu *ulast = NULL;
1217 struct feu *f = NULL;
1218
1220
1221 // Phase 1 : build a linked list of all our user account names
1222 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
1223 usptr = (struct ctdluser *) cdbus->ptr;
1224
1225 if (strlen(usptr->fullname) > 0) {
1226 f = malloc(sizeof(struct feu));
1227 f->next = NULL;
1228 strncpy(f->username, usptr->fullname, USERNAME_SIZE);
1229
1230 if (ufirst == NULL) {
1231 ufirst = f;
1232 ulast = f;
1233 }
1234 else {
1235 ulast->next = f;
1236 ulast = f;
1237 }
1238 }
1239 }
1240
1241 // Phase 2 : perform the callback for each user while de-allocating the list
1242 while (ufirst != NULL) {
1243 (*CallBack) (ufirst->username, in_data);
1244 f = ufirst;
1245 ufirst = ufirst->next;
1246 free(f);
1247 }
1248}
1249
1250
1251/*
1252 * Count the number of new mail messages the user has
1253 */
1255{
1256 int num_newmsgs = 0;
1257 num_newmsgs = CC->newmail;
1258 CC->newmail = 0;
1259 return(num_newmsgs);
1260}
1261
1262
1263/*
1264 * Count the number of new mail messages the user has
1265 */
1267{
1268 int num_newmsgs = 0;
1269 int a;
1270 char mailboxname[ROOMNAMELEN];
1271 struct ctdlroom mailbox;
1272 visit vbuf;
1273 struct cdbdata *cdbfr;
1274 long *msglist = NULL;
1275 int num_msgs = 0;
1276
1277 CtdlMailboxName(mailboxname, sizeof mailboxname, &CC->user, MAILROOM);
1278 if (CtdlGetRoom(&mailbox, mailboxname) != 0)
1279 return(0);
1280 CtdlGetRelationship(&vbuf, &CC->user, &mailbox);
1281
1282 cdbfr = cdb_fetch(CDB_MSGLISTS, &mailbox.QRnumber, sizeof(long));
1283
1284 if (cdbfr != NULL) {
1285 msglist = malloc(cdbfr->len);
1286 memcpy(msglist, cdbfr->ptr, cdbfr->len);
1287 num_msgs = cdbfr->len / sizeof(long);
1288 cdb_free(cdbfr);
1289 }
1290 if (num_msgs > 0)
1291 for (a = 0; a < num_msgs; ++a) {
1292 if (msglist[a] > 0L) {
1293 if (msglist[a] > vbuf.v_lastseen) {
1294 ++num_newmsgs;
1295 }
1296 }
1297 }
1298 if (msglist != NULL)
1299 free(msglist);
1300
1301 return(num_newmsgs);
1302}
#define ROOMNAMELEN
Definition: citadel.h:56
#define AUTHMODE_HOST
Definition: citadel.h:174
#define REV_LEVEL
Definition: citadel.h:35
#define AUTHMODE_LDAP
Definition: citadel.h:175
#define USERNAME_SIZE
Definition: citadel.h:57
#define AUTHMODE_LDAP_AD
Definition: citadel.h:176
#define file_chkpwd
Definition: citadel_dirs.h:36
int CtdlTryPasswordLDAP(char *user_dn, const char *password)
int extract_email_addresses_from_ldap(char *ldap_dn, char *emailaddrs)
int CtdlTryUserLDAP(char *username, char *found_dn, int found_dn_size, char *fullname, int fullname_size, uid_t *found_uid)
char * CtdlGetConfigStr(char *key)
Definition: config.c:393
int CtdlGetConfigInt(char *key)
Definition: config.c:426
CitContext * MyContext(void)
Definition: context.c:201
int CtdlIsUserLoggedInByNum(long usernum)
Definition: context.c:177
int CtdlIsUserLoggedIn(char *user_name)
Definition: context.c:152
#define CC
Definition: context.h:140
long get_new_user_number(void)
Definition: control.c:208
int attach_extauth(struct ctdluser *who, StrBuf *claimed_id)
int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name)
Definition: room_ops.c:342
#define CtdlAideMessage(TEXT, SUBJECT)
Definition: ctdl_module.h:58
int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name)
Definition: room_ops.c:387
@ pass_internal_error
Definition: ctdl_module.h:293
@ pass_ok
Definition: ctdl_module.h:290
@ pass_no_user
Definition: ctdl_module.h:292
@ pass_already_logged_in
Definition: ctdl_module.h:291
@ pass_wrong_password
Definition: ctdl_module.h:294
@ login_too_many_users
Definition: ctdl_module.h:304
@ login_not_found
Definition: ctdl_module.h:305
@ login_ok
Definition: ctdl_module.h:302
@ login_already_logged_in
Definition: ctdl_module.h:303
@ ac_room_aide
Definition: ctdl_module.h:245
@ ac_logged_in_or_guest
Definition: ctdl_module.h:243
@ ac_aide
Definition: ctdl_module.h:246
@ ac_logged_in
Definition: ctdl_module.h:244
@ ac_internal
Definition: ctdl_module.h:247
unsigned CtdlCreateRoom(char *new_room_name, int new_room_type, char *new_room_pass, int new_room_floor, int really_create, int avoid_access, int new_room_view)
Definition: room_ops.c:1136
void CtdlUserGoto(char *where, int display_result, int transiently, int *msgs, int *new, long *oldest, long *newest)
Definition: room_ops.c:702
void CtdlPutRoomLock(struct ctdlroom *qrbuf)
Definition: room_ops.c:444
void cdb_free(struct cdbdata *cdb)
Definition: database.c:609
struct cdbdata * cdb_next_item(int cdb)
Definition: database.c:655
int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen)
Definition: database.c:397
struct cdbdata * cdb_fetch(int cdb, const void *key, int keylen)
Definition: database.c:546
int cdb_delete(int cdb, void *key, int keylen)
Definition: database.c:482
void cdb_trunc(int cdb)
Definition: database.c:726
void cdb_rewind(int cdb)
Definition: database.c:631
struct recptypes * validate_recipients(char *supplied_recipients, const char *RemoteIdentifier, int Flags)
void free_recipients(struct recptypes *valid)
void CtdlSetEmailAddressesForUser(char *requested_user, char *new_emailaddrs)
void AutoGenerateEmailAddressForUser(struct ctdluser *user)
#define CIT_OK
Definition: ipcdef.h:6
#define US_PAGINATOR
Definition: ipcdef.h:71
#define US_FLOORS
Definition: ipcdef.h:73
#define INTERNAL_ERROR
Definition: ipcdef.h:14
#define HIGHER_ACCESS_REQUIRED
Definition: ipcdef.h:23
#define US_DISAPPEAR
Definition: ipcdef.h:69
#define US_LASTOLD
Definition: ipcdef.h:64
#define QR_MAILBOX
Definition: ipcdef.h:53
#define NOT_LOGGED_IN
Definition: ipcdef.h:17
#define ERROR
Definition: ipcdef.h:9
#define ALREADY_EXISTS
Definition: ipcdef.h:33
#define QR2_SYSTEM
Definition: ipcdef.h:55
#define NO_SUCH_USER
Definition: ipcdef.h:29
#define US_INTERNET
Definition: ipcdef.h:72
void * malloc(size_t)
void free(void *)
void PerformSessionHooks(int EventType)
void PerformUserHooks(ctdluser *usbuf, int EventType)
struct ctdlroom qrbuf
Definition: serv_migrate.c:497
visit vbuf
Definition: serv_migrate.c:503
struct ctdluser usbuf
Definition: serv_migrate.c:496
#define EVT_LOGOUT
Definition: server.h:216
#define EVT_NEWUSER
Definition: server.h:229
#define V_FORGET
Definition: server.h:256
#define EVT_LOGIN
Definition: server.h:214
#define V_ACCESS
Definition: server.h:258
#define EVT_SETPASS
Definition: server.h:217
#define EVT_PURGEUSER
Definition: server.h:228
@ CDB_VISIT
Definition: server.h:190
@ CDB_USERSBYNUMBER
Definition: server.h:196
@ CDB_EXTAUTH
Definition: server.h:197
@ CDB_MSGLISTS
Definition: server.h:189
@ CDB_USERS
Definition: server.h:186
#define V_LOCKOUT
Definition: server.h:257
@ S_CHKPWD
Definition: server.h:150
@ S_USERS
Definition: server.h:135
int snprintf(char *buf, size_t max, const char *fmt,...)
Definition: snprintf.c:69
int cs_pid
Definition: context.h:44
int logged_in
Definition: context.h:70
char cs_inet_other_emails[1024]
Definition: context.h:96
long tcp_port
Definition: context.h:126
char cs_inet_fn[128]
Definition: context.h:97
struct ctdluser user
Definition: context.h:109
const char * ServiceName
Definition: context.h:125
char curr_user[64]
Definition: context.h:69
char cs_addr[64]
Definition: context.h:91
char cs_inet_email[128]
Definition: context.h:95
char * ldap_dn
Definition: context.h:128
char cs_host[64]
Definition: context.h:90
long v_lastseen
Definition: server.h:249
long v_roomgen
Definition: server.h:247
long v_roomnum
Definition: server.h:246
long v_usernum
Definition: server.h:248
unsigned int v_flags
Definition: server.h:250
char v_seen[4096]
Definition: server.h:251
int v_view
Definition: server.h:253
size_t len
Definition: server.h:203
char * ptr
Definition: server.h:204
unsigned QRflags2
Definition: citadel.h:121
long QRnumber
Definition: citadel.h:119
time_t QRgen
Definition: citadel.h:112
int QRdefaultview
Definition: citadel.h:122
long posted
Definition: citadel.h:85
unsigned flags
Definition: citadel.h:83
cit_uint8_t axlevel
Definition: citadel.h:86
char fullname[64]
Definition: citadel.h:90
time_t lastcall
Definition: citadel.h:88
long timescalled
Definition: citadel.h:84
uid_t uid
Definition: citadel.h:81
long usernum
Definition: citadel.h:87
int version
Definition: citadel.h:80
char password[32]
Definition: citadel.h:82
char * recp_local
Definition: server.h:55
int num_local
Definition: server.h:49
void strproc(char *string)
Definition: support.c:17
#define USERCONFIGROOM
Definition: sysconfig.h:64
#define MAILROOM
Definition: sysconfig.h:61
#define USERDRAFTROOM
Definition: sysconfig.h:69
#define SENTITEMS
Definition: sysconfig.h:62
#define USERTRASHROOM
Definition: sysconfig.h:70
#define SIZ
Definition: sysconfig.h:33
#define NLI
Definition: sysconfig.h:18
void cprintf(const char *format,...)
Definition: sysdep.c:381
void unbuffer_output(void)
Definition: sysdep.c:276
void begin_critical_section(int which_one)
Definition: threads.c:67
void end_critical_section(int which_one)
Definition: threads.c:85
void CtdlGetRelationship(visit *vbuf, struct ctdluser *rel_user, struct ctdlroom *rel_room)
Definition: user_ops.c:321
void CtdlPutUser(struct ctdluser *usbuf)
Definition: user_ops.c:128
void CtdlMailboxName(char *buf, size_t n, const struct ctdluser *who, const char *prefix)
Definition: user_ops.c:351
void ForEachUser(void(*CallBack)(char *, void *out_data), void *in_data)
Definition: user_ops.c:1206
int CtdlLockGetCurrentUser(void)
Definition: user_ops.c:103
int CtdlLoginExistingUser(const char *trythisname)
Definition: user_ops.c:535
int internal_create_user(char *username, struct ctdluser *usbuf, uid_t uid)
Definition: user_ops.c:1018
void CtdlSetPassword(char *new_pw)
Definition: user_ops.c:1126
void do_login(void)
Definition: user_ops.c:662
int CtdlUserCmp(char *s1, char *s2)
Definition: user_ops.c:63
int CtdlAccessCheck(int required_level)
Definition: user_ops.c:389
int is_aide(void)
Definition: user_ops.c:429
void MailboxName(char *buf, size_t n, const struct ctdluser *who, const char *prefix)
Definition: user_ops.c:357
void rebuild_usersbynumber(void)
Definition: user_ops.c:496
void reindex_user_928(char *username, void *out_data)
Definition: user_ops.c:232
int getuserbyuid(struct ctdluser *usbuf, uid_t number)
Definition: user_ops.c:507
int purge_user(char pname[])
Definition: user_ops.c:972
void CtdlPutCurrentUserLock()
Definition: user_ops.c:138
int NewMailCount()
Definition: user_ops.c:1254
int CtdlGetUserByNumber(struct ctdluser *usbuf, long number)
Definition: user_ops.c:462
static int validpw(uid_t uid, const char *pass)
Definition: user_ops.c:787
int create_user(char *username, int become_user, uid_t uid)
Definition: user_ops.c:1065
int CtdlForgetThisRoom(void)
Definition: user_ops.c:1178
int GenerateRelationshipIndex(char *IndexBuf, long RoomID, long RoomGen, long UserID)
Definition: user_ops.c:264
int CtdlCheckInternetMailPermission(struct ctdluser *who)
Definition: user_ops.c:367
int is_room_aide(void)
Definition: user_ops.c:441
void CtdlUserLogout(void)
Definition: user_ops.c:750
void put_visit(visit *newvisit)
Definition: user_ops.c:287
int CtdlGetUserLock(struct ctdluser *usbuf, char *name)
Definition: user_ops.c:113
void makeuserkey_pre928(char *key, const char *username)
Definition: user_ops.c:213
int CtdlInvtKick(char *iuser, int op)
Definition: user_ops.c:1142
void makeuserkey(char *key, const char *username)
Definition: user_ops.c:40
int rename_user(char *oldname, char *newname)
Definition: user_ops.c:160
void logged_in_response(void)
Definition: user_ops.c:739
void start_chkpwd_daemon(void)
Definition: user_ops.c:833
int CtdlTryPassword(const char *password, long len)
Definition: user_ops.c:870
void CtdlPutUserLock(struct ctdluser *usbuf)
Definition: user_ops.c:147
void CtdlSetRelationship(visit *newvisit, struct ctdluser *rel_user, struct ctdlroom *rel_room)
Definition: user_ops.c:306
int InitialMailCheck()
Definition: user_ops.c:1266
void rebuild_ubn_for_user(char *username, void *data)
Definition: user_ops.c:483
int chkpwd_read_pipe[2]
Definition: user_ops.c:32
int chkpwd_write_pipe[2]
Definition: user_ops.c:31
int CtdlGetUser(struct ctdluser *usbuf, char *name)
Definition: user_ops.c:77
#define RENAMEUSER_NOT_FOUND
Definition: user_ops.h:66
#define RENAMEUSER_OK
Definition: user_ops.h:64
@ CREATE_USER_BECOME_USER
Definition: user_ops.h:34
@ CREATE_USER_DO_NOT_BECOME_USER
Definition: user_ops.h:33
#define RENAMEUSER_LOGGED_IN
Definition: user_ops.h:65
#define RENAMEUSER_ALREADY_EXISTS
Definition: user_ops.h:67
#define NATIVE_AUTH_UID
Definition: user_ops.h:36