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