person.c 25.8 KB
Newer Older
Linus Tolke Y's avatar
Linus Tolke Y committed
1
/*
Per Cederqvist's avatar
Per Cederqvist committed
2
 * $Id: person.c,v 0.53 1999/06/03 22:11:08 ceder Exp $
3
 * Copyright (C) 1991-1999  Lysator Academic Computer Association.
Linus Tolke Y's avatar
Linus Tolke Y committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * This file is part of the LysKOM server.
 * 
 * LysKOM is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 1, or (at your option) 
 * any later version.
 * 
 * LysKOM is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with LysKOM; see the file COPYING.  If not, write to
 * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
 * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
 * MA 02139, USA.
 *
 * Please mail bug reports to bug-lyskom@lysator.liu.se. 
 */
Per Cederqvist's avatar
Per Cederqvist committed
25
26
27
28
29
/*
 * person.c
 *
 * All atomic calls that deals with persons.
 */
Per Cederqvist's avatar
Per Cederqvist committed
30

David Byers's avatar
David Byers committed
31
32
33
34
35
36


#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

37
static const char *
Per Cederqvist's avatar
Per Cederqvist committed
38
rcsid = "$Id: person.c,v 0.53 1999/06/03 22:11:08 ceder Exp $";
39
40
#include "rcs.h"
USE(rcsid);
Per Cederqvist's avatar
Per Cederqvist committed
41

Per Cederqvist's avatar
Per Cederqvist committed
42
43
#include <limits.h>
#include <stdio.h>
44
45
46
47
48
49
#ifdef HAVE_STDLIB_H
#  include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#  include <string.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
50
#include <time.h>
51
52
53
#ifdef HAVE_UNISTD_H
#  include <unistd.h>		/* for crypt() on Linux */
#endif
Per Cederqvist's avatar
Per Cederqvist committed
54
#include <setjmp.h>
Per Cederqvist's avatar
Per Cederqvist committed
55
#include <sys/types.h>
56
57
#ifdef HAVE_CRYPT_H
#  include <crypt.h>
58
#endif
Per Cederqvist's avatar
Per Cederqvist committed
59

Per Cederqvist's avatar
Per Cederqvist committed
60
61
62
63
#include "misc-types.h"
#include "s-string.h"
#include "kom-types.h"
#include "services.h"
David Byers's avatar
Server  
David Byers committed
64
65
66
#include "com.h"
#include "async.h"
#include "connections.h"
Per Cederqvist's avatar
Per Cederqvist committed
67
#include "manipulate.h"
Per Cederqvist's avatar
Per Cederqvist committed
68
#include "string-malloc.h"
Per Cederqvist's avatar
Per Cederqvist committed
69
#include "debug.h"
Per Cederqvist's avatar
Per Cederqvist committed
70
#include "cache.h"
Per Cederqvist's avatar
Per Cederqvist committed
71
72
#include "kom-errno.h"
#include "server/smalloc.h"
David Byers's avatar
David Byers committed
73
#include "kom-config.h"
Per Cederqvist's avatar
Per Cederqvist committed
74
75
76
#include "log.h"
#include "minmax.h"
#include "lyskomd.h"
77
#include "param.h"
78
#include "aux-items.h"
79
#include "local-to-global.h"
David Byers's avatar
David Byers committed
80
#include "kom-memory.h"
81
#include "server-time.h"
82

David Byers's avatar
David Byers committed
83
84
BUGDECL;

Per Cederqvist's avatar
Per Cederqvist committed
85
86
87
/*
 * Static functions.
 */
88

Per Cederqvist's avatar
Per Cederqvist committed
89
90
91
static Bool
legal_passwd(const String pwd)
{
92
93
94
95
96
97
98
    int i;

    for (i = 0; i < s_strlen(pwd); i++)
	if (pwd.string[i] == '\0')
	    return FALSE;

    return TRUE; 
Per Cederqvist's avatar
Per Cederqvist committed
99
100
101
102
103
104
}

static Success
do_set_passwd( Password        pwd,
	       const String   new_pwd)
{
Per Cederqvist's avatar
Per Cederqvist committed
105
106
#ifdef ENCRYPT_PASSWORDS
    char salt[3];
Per Cederqvist's avatar
Per Cederqvist committed
107
108
    static char crypt_seed[] = 
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
109
    char *password;
Per Cederqvist's avatar
Per Cederqvist committed
110

Per Cederqvist's avatar
Per Cederqvist committed
111
112
    if ( !legal_passwd(new_pwd) )
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
113

114
115
    salt[0] = crypt_seed [rand() % (sizeof (crypt_seed) - 1)];
    salt[1] = crypt_seed [rand() % (sizeof (crypt_seed) - 1)];
Per Cederqvist's avatar
Per Cederqvist committed
116
    salt[2] = '\0';
117
118
119
120
121
122
123

    password = s_crea_c_str(new_pwd);
    if (password == NULL)
	return FAILURE;
    else
    {
	strcpy((char *)pwd, (const char *)crypt(password, salt));
124
	string_free(password);
125
126
	return OK;
    }
Per Cederqvist's avatar
Per Cederqvist committed
127
128
129
130
131
132
133
134

#else

    /* Compatibility mode... */
    if ( !legal_passwd(new_pwd) )
	return FAILURE;

    *pwd++ = new_pwd.len;		/* Indeed too easy crypt... */
Per Cederqvist's avatar
Per Cederqvist committed
135
136
    strncpy(pwd, (const char *)new_pwd.string,
	    min( PASSWD_LEN-1, new_pwd.len ));
Per Cederqvist's avatar
Per Cederqvist committed
137

Per Cederqvist's avatar
Per Cederqvist committed
138
    return OK;
139
140

#endif
Per Cederqvist's avatar
Per Cederqvist committed
141
142
143
144
145
146
}



/*
 * Mark a text. No check is done if pers_p is really allowed to mark it.
147
148
 * This function can mark a text with mark_type == 0.  If a previous mark
 * existed it is changed to the given mark_type.
Per Cederqvist's avatar
Per Cederqvist committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
 */

static Success
do_mark_text(Pers_no    pers_no,
	     Person    *pers_p,		/* May be NULL */
	     Text_no    text_no,
	     Text_stat *text_s,		/* May be NULL */
	     u_char     mark_type)
{
    Mark      *markp;
    Mark      *old_mark = NULL;
    int        i;

    if ( pers_p == NULL )
	GET_P_STAT(pers_p, pers_no, FAILURE);
	
    /* Locate the mark. */
    
    for ( i = pers_p->marks.no_of_marks, markp = pers_p->marks.marks;
	 i > 0 && old_mark == NULL;
	 i--, markp++ )
    {
	if ( markp->text_no == text_no )
	    old_mark = markp;
    }

175
    if (old_mark != NULL)
Per Cederqvist's avatar
Per Cederqvist committed
176
177
178
179
180
181
182
183
    {
	/* Change marktype of an already marked text. (No need to check
	   that the text exists). */
	BUG(("do_mark_text(): Change type of mark.\n"));
	
	old_mark->mark_type = mark_type;
	mark_person_as_changed(pers_no);
    }
184
185
186
187
188
189
190
191
    else
    {
	/* A new mark. Check that the text exists. */
	BUG(("do_mark_text(): new mark.\n"));

	if ( text_s == NULL )
	    GET_T_STAT(text_s, text_no, FAILURE);

192
193
	if (text_s->no_of_marks >= param.max_marks_text
	    || pers_p->marks.no_of_marks >= param.max_marks_person)
194
	{
195
            err_stat = text_no;
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	    kom_errno = KOM_MARK_LIMIT;
	    return FAILURE;
	}

	text_s->no_of_marks++;
	mark_text_as_changed(text_no);
	
	pers_p->marks.marks = srealloc(pers_p->marks.marks,
			       ++pers_p->marks.no_of_marks * sizeof(Mark));
	pers_p->marks.marks[pers_p->marks.no_of_marks - 1].text_no = text_no;
	pers_p->marks.marks[pers_p->marks.no_of_marks - 1].mark_type
	    = mark_type;
	mark_person_as_changed(pers_no);
    }
    
    return OK;
}

/* Unmark a text. Returns a failure if the text was not marked. */

static Success
do_unmark_text(Pers_no    pers_no,
	       Person    *pers_p, /* May be NULL */
	       Text_no    text_no,
	       Text_stat *text_s) /* May be NULL */
{
    Mark      *markp;
    Mark      *old_mark = NULL;
    int        i;

    if ( pers_p == NULL )
	GET_P_STAT(pers_p, pers_no, FAILURE);
	
    /* Locate the mark. */
    
    for ( i = pers_p->marks.no_of_marks, markp = pers_p->marks.marks;
	 i > 0 && old_mark == NULL;
	 i--, markp++ )
    {
	if ( markp->text_no == text_no )
	    old_mark = markp;
    }

    if (old_mark != NULL)
Per Cederqvist's avatar
Per Cederqvist committed
240
241
    {
	/* Delete this mark. */
242
	BUG(("do_unmark_text(): Delete mark.\n"));
Per Cederqvist's avatar
Per Cederqvist committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	
	while ( old_mark < ( pers_p->marks.marks
			    + pers_p->marks.no_of_marks - 1 ))
	{
	    *old_mark = *(old_mark + 1);
	    old_mark++;
	}

	pers_p->marks.no_of_marks--;
	mark_person_as_changed(pers_no);
	
	/* ...and don't forget to decrease the ref_cnt in the text_stat... */

	if ( (text_s = cached_get_text_stat(text_no)) != NULL )
	{
	    if ( text_s->no_of_marks == 0 )
	    {
David Byers's avatar
David Byers committed
260
		kom_log("WNG: do_unmark_text(): Text %lu has no_of_marks==0,\
Per Cederqvist's avatar
Per Cederqvist committed
261
 		     but person %d had marked the text.",
262
		    (unsigned long)text_no, pers_no);
Per Cederqvist's avatar
Per Cederqvist committed
263
264
265
266
267
268
269
270
271
272
273
	    }
	    else
	    {
		text_s->no_of_marks--;
		mark_text_as_changed(text_no);
	    }
	}
	/* ...but it is not an error if someone has deleted the text. */
    }
    else
    {
274
275
	/* An attempt to delete a non-existent mark. */
	BUG(("do_unmark_text(): delete non-existent mark.\n"));
276
        err_stat = text_no;
277
278
	kom_errno = KOM_NOT_MARKED;
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
279
280
281
282
283
284
285
286
287
288
289
290
291
    }
    
    return OK;
}


/*
 * Change user_area of a person. If text_no is 0, there will be
 * no user_area.
 */

static Success
do_set_user_area(Pers_no     pers_no,
292
293
		 Person	   * pers_p, /* May be NULL */
		 Text_no     user_area)
Per Cederqvist's avatar
Per Cederqvist committed
294
295
296
297
{
    Text_stat * old_user_area;
    Text_stat * new_user_area = NULL; /* To stop gcc complaining. */

298
    /* Check that the new user_area exists before deleting the old*/
Per Cederqvist's avatar
Per Cederqvist committed
299

300
    if ( user_area != 0 )
Per Cederqvist's avatar
Per Cederqvist committed
301
    {
302
	GET_T_STAT(new_user_area, user_area, FAILURE);
303
	if ( new_user_area->no_of_marks >= param.max_marks_text )
Per Cederqvist's avatar
Per Cederqvist committed
304
	{
David Byers's avatar
David Byers committed
305
	    kom_log("%s(%d, %lu): New user_area's mark count (%d) > %d.\n",
Per Cederqvist's avatar
Per Cederqvist committed
306
		"LIMIT: set_user_area",
307
		pers_no, (unsigned long)user_area, new_user_area->no_of_marks,
308
		param.max_marks_text);
309
            err_stat = user_area;
310
	    kom_errno = KOM_MARK_LIMIT;
Per Cederqvist's avatar
Per Cederqvist committed
311
312
313
	    return FAILURE;
	}
    }
314
315
316

    if ( pers_p == NULL )
	GET_P_STAT(pers_p, pers_no, FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
317
318
319
320
    
    /* Unmark the previous user_area if it exists. */

    if ( pers_p->user_area != 0
321
	&& (old_user_area = cached_get_text_stat(pers_p->user_area)) != NULL)
Per Cederqvist's avatar
Per Cederqvist committed
322
323
324
325
    {
	if ( old_user_area->no_of_marks > 0 )
	{
	    --old_user_area->no_of_marks;
326
	    mark_text_as_changed( pers_p->user_area );
Per Cederqvist's avatar
Per Cederqvist committed
327
328
329
	}
	else
	{
David Byers's avatar
David Byers committed
330
	    kom_log("ERROR: set_user_area(%d, %lu): Old user_area %lu unmarked\n",
331
332
		pers_no, (unsigned long)user_area,
		(unsigned long)pers_p->user_area);
Per Cederqvist's avatar
Per Cederqvist committed
333
334
335
336
337
	}
    }

    /* Mark the new user_area */

338
    if ( user_area != 0 )
Per Cederqvist's avatar
Per Cederqvist committed
339
340
    {
	++new_user_area->no_of_marks;
341
	mark_text_as_changed( user_area );
Per Cederqvist's avatar
Per Cederqvist committed
342
343
    }
    
344
345
    pers_p->user_area = user_area;
    mark_person_as_changed (pers_no);
Per Cederqvist's avatar
Per Cederqvist committed
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

    return OK;
}
/*
 * End of static functions.
 */

/*
 * Functions that are exported to the server.
 */

/*
 * Delete a person. (The mailbox is not deleted).
 */

Success
do_delete_pers (Pers_no pers_no)
{
    Person * pers_p;
    int	     i;
    
    GET_P_STAT(pers_p, pers_no, FAILURE);

    /* Cancel membership in all confs. */
    /* Note that because of the way do_sub_member is written the */
    /* loop must be executed this way. */
    for ( i = pers_p->conferences.no_of_confs - 1; i >= 0; i-- )
    {
	if ( do_sub_member( pers_p->conferences.confs[ i ].conf_no, NULL, NULL,
			   pers_no, pers_p,
			   pers_p->conferences.confs + i) != OK)
	{
David Byers's avatar
David Byers committed
378
	    kom_log("ERROR: do_delete_pers(): can't sub_member\n");
Per Cederqvist's avatar
Per Cederqvist committed
379
380
381
382
383
	}
    }

    for ( i = pers_p->marks.no_of_marks; i > 0; i-- )
    {
384
385
	if ( do_unmark_text(pers_no, pers_p,
			    pers_p->marks.marks[0].text_no, NULL) != OK )
Per Cederqvist's avatar
Per Cederqvist committed
386
	{
David Byers's avatar
David Byers committed
387
	    kom_log("WNG: do_delete_pers(): can't unmark text %lu (i == %d)\n",
388
		(unsigned long)pers_p->marks.marks[0].text_no, i);
Per Cederqvist's avatar
Per Cederqvist committed
389
390
391
392
393
	}
    }
    
    if ( do_set_user_area(pers_no, pers_p, 0) != OK )
    {
David Byers's avatar
David Byers committed
394
	kom_log("WNG: do_delete_pers(): can't unmark user_area\n");
Per Cederqvist's avatar
Per Cederqvist committed
395
396
397
    }

    s_clear( &pers_p->username );
398
    l2g_clear(&pers_p->created_texts);
Per Cederqvist's avatar
Per Cederqvist committed
399
400
401
402
403
404
405
406
407
408
409

    cached_delete_person(pers_no);
    
    /* ASYNC */
    return OK;    
}

/*
 * Check a password
 */
Success
Per Cederqvist's avatar
Per Cederqvist committed
410
411
chk_passwd (Password      pwd,
	    const String  try)
Per Cederqvist's avatar
Per Cederqvist committed
412
{
Per Cederqvist's avatar
Per Cederqvist committed
413
#ifdef ENCRYPT_PASSWORDS
414
    char *c_try;
Per Cederqvist's avatar
Per Cederqvist committed
415

416
417
418
419
    c_try = s_crea_c_str(try);
    if (c_try == NULL)
	return FAILURE;
    
Per Cederqvist's avatar
Per Cederqvist committed
420
    if (strcmp ((const char *)pwd,
421
422
		(const char *)crypt(c_try, (const char *)pwd)) != 0)
    {
423
	string_free(c_try);
Per Cederqvist's avatar
Per Cederqvist committed
424
	return FAILURE;
425
    }
Per Cederqvist's avatar
Per Cederqvist committed
426
    else
427
    {
428
	string_free(c_try);
Per Cederqvist's avatar
Per Cederqvist committed
429
	return OK;
430
    }
Per Cederqvist's avatar
Per Cederqvist committed
431
432
433

#else

Per Cederqvist's avatar
Per Cederqvist committed
434
435
    int i;
    
Per Cederqvist's avatar
Per Cederqvist committed
436
    if ( try.len != *pwd )
Per Cederqvist's avatar
Per Cederqvist committed
437
438
	return FAILURE;

Per Cederqvist's avatar
Per Cederqvist committed
439
440
    for ( i = 0; i < try.len; i++ )
	if ( pwd[ i + 1 ] != try.string[ i ] )
Per Cederqvist's avatar
Per Cederqvist committed
441
442
443
	    return FAILURE;

    return OK;
Per Cederqvist's avatar
Per Cederqvist committed
444
445

#endif
Per Cederqvist's avatar
Per Cederqvist committed
446
447
448
449
450
451
452
453
454
455
456
457
458
459
}


/*
 * Mark a text.
 *
 * If the you already have marked the text the mark-type will be changed. 
 * If mark_type == 0 the mark will be deleted. You can only mark texts
 * that you are allowed to read. You are always allowed to read all
 * texts that you have marked even if you are no longer a recipient
 * of the text.
 */

extern Success
460
461
462
463
464
465
466
467
468
469
470
471
mark_text_old(Text_no text_no,
	      u_char mark_type)
{
    if (mark_type == 0)
	return unmark_text(text_no);
    else
	return mark_text(text_no, mark_type);
}

extern Success
mark_text(Text_no text_no,   /* Will fail if the user is not */
	  u_char mark_type)	/* allowed to read the text.	*/
Per Cederqvist's avatar
Per Cederqvist committed
472
473
474
{
    Text_stat *text_s = NULL;
        
David Byers's avatar
Server  
David Byers committed
475
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
476
477
    CHK_LOGIN(FAILURE);

478
479
    /* Check that the user is allowed to read the text. */
    GET_T_STAT(text_s, text_no, FAILURE);
David Byers's avatar
Server  
David Byers committed
480
    if ( !text_read_access(active_connection, text_no, text_s) )
Per Cederqvist's avatar
Per Cederqvist committed
481
    {
482
        err_stat = text_no;
David Byers's avatar
David Byers committed
483
	kom_errno = KOM_NO_SUCH_TEXT;
484
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
485
486
    }

487
    BUG(("Person %d markerar text %lu med typ %d\n",
Per Cederqvist's avatar
Per Cederqvist committed
488
489
490
491
492
	 ACTPERS, text_no, mark_type));
    
    return do_mark_text(ACTPERS, ACT_P, text_no, text_s, mark_type);
}

493
494
495
496
497
extern Success
unmark_text(Text_no text_no)
{
    Text_stat *text_s = NULL;
        
David Byers's avatar
Server  
David Byers committed
498
    CHK_CONNECTION(FAILURE);
499
    CHK_LOGIN(FAILURE);
500
    BUG(("Person %d avmarkerar text %lu\n", ACTPERS, text_no));
501
502
503
504
    
    return do_unmark_text(ACTPERS, ACT_P, text_no, text_s);
}

Per Cederqvist's avatar
Per Cederqvist committed
505
506
507
/*
 * Create a new person.
 *
508
 * If parameter ``Anyone can create new persons'' is true
Per Cederqvist's avatar
Per Cederqvist committed
509
 * anyone can create themself. Otherwise you must be logged in to
510
511
 * create a new person, and you must have the ``create_pers'' bit
 * set, or ``Anyone can create_new_persons'' must be set.
Per Cederqvist's avatar
Per Cederqvist committed
512
513
514
515
516
517
518
519
520
 *
 * If you are not logged in an auto-login as the created person is
 * performed. (This is so that it is impossible to create a million
 * persons (and so destroy the database) anonymously. This way it will
 * at least be possible to see from which machine the attack came).
 *
 * If you are logged in you will be supervisor and creator of the new
 * person, otherwise the new person will be supervisor and creator.
 *
521
522
523
 * The new person will be rd_prot, but not secret. He will have no
 * privileges, except maybe change_name (if ``Default change name
 * capability'' is true).
Per Cederqvist's avatar
Per Cederqvist committed
524
525
526
527
 *
 * This function returns the Pers_no of the new person, or 0 if an error
 * occured. (0 is an illegal Pers_no).
 */
528
529
530
531

static Pers_no
create_person_generic ( const String  name,
                        const String  passwd,
532
                        Aux_item_list *conf_aux,
David Byers's avatar
David Byers committed
533
                        Personal_flags flags,
534
                        Bool do_auto_login )
Per Cederqvist's avatar
Per Cederqvist committed
535
536
537
538
{
    Pers_no 	  new_user;
    Conference	* mailbox;
    Person	* pers_p;
539
    Membership_type mship_type;
Per Cederqvist's avatar
Per Cederqvist committed
540

David Byers's avatar
Server  
David Byers committed
541
    CHK_CONNECTION(0);
542
    if (ACTPERS == 0)
Per Cederqvist's avatar
Per Cederqvist committed
543
    {
544
545
	if (!param.create_person_before_login && ACTPERS == 0 )
	{
546
            err_stat = 0;
547
548
549
550
551
552
553
	    kom_errno = KOM_LOGIN;
	    return 0;
	}
    }
    else
    {
	if (param.anyone_can_create_new_persons == FALSE
David Byers's avatar
Server  
David Byers committed
554
	    && !HAVE_PRIV(ACT_P, create_pers))
555
	{
556
            err_stat = 0;
557
558
559
	    kom_errno = KOM_PERM;
	    return 0;
	}
Per Cederqvist's avatar
Per Cederqvist committed
560
561
562
563
564
    }

#if 0
    if ( !logins_allowed  && !ACTPERS ) /* A new user can't create himself */
    {					/* if he isn't allowed to login. */
565
        err_stat = 0;
Per Cederqvist's avatar
Per Cederqvist committed
566
567
568
569
570
571
572
	kom_errno = KOM_LOGIN_DISALLOWED;
	return 0;
    }
#endif

    if ( !legal_name( name ) )
    {
573
	/* kom_errno will be set by legal_name(). */
Per Cederqvist's avatar
Per Cederqvist committed
574
575
576
577
578
	return 0;
    }

    if ( !unique_name( name, 0 ) )
    {
579
        err_stat = 0;
David Byers's avatar
David Byers committed
580
	kom_errno = KOM_PERS_EXISTS;
Per Cederqvist's avatar
Per Cederqvist committed
581
582
583
584
585
	return 0;
    }

    if ( !legal_passwd( passwd ) )
    {
586
        err_stat = 0;
Per Cederqvist's avatar
Per Cederqvist committed
587
588
589
590
591
	kom_errno = KOM_PWD;
	return 0;
    }

    new_user = cached_create_conf( name );
David Byers's avatar
David Byers committed
592
593
594
595
596
597
    if (new_user == 0)
    {
        /* kom_errno and err_stat set in cached_create_conf */
        kom_log("ERROR: Couldn't create person. Too many conferences.");
        return 0;
    }
Per Cederqvist's avatar
Per Cederqvist committed
598
599
600
601
602
603
604

    if ( (mailbox = cached_get_conf_stat( new_user ) ) == NULL)
    {
	restart_kom("create_person() - can't get conf_stat");
    }
    
    mailbox->creator		= ACTPERS ? ACTPERS : new_user;
605
    mailbox->creation_time 	= current_time;
Per Cederqvist's avatar
Per Cederqvist committed
606
607
608
609
610
611
612
613
    mailbox->presentation	= 0;		/* No presentation yet */
    mailbox->supervisor		= ACTPERS ? ACTPERS : new_user;
    mailbox->permitted_submitters = 0;
    mailbox->super_conf		= ACTPERS;
    mailbox->type.rd_prot	= 1;
    mailbox->type.original	= 0;
    mailbox->type.secret	= 0;
    mailbox->type.letter_box	= 1;
614
    mailbox->type.allow_anon    = 1;
David Byers's avatar
David Byers committed
615
    mailbox->type.forbid_secret = 0;
616
617
    mailbox->type.reserved2     = 0;
    mailbox->type.reserved3     = 0;
Per Cederqvist's avatar
Per Cederqvist committed
618
619
    mailbox->last_written	= mailbox->creation_time;
    mailbox->msg_of_day		= 0;
620
    mailbox->nice		= param.default_nice;
621
    mailbox->keep_commented     = param.default_keep_commented;
Per Cederqvist's avatar
Per Cederqvist committed
622

623
    mark_conference_as_changed (new_user);
Per Cederqvist's avatar
Per Cederqvist committed
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

    /* allocate Person */

    if ( cached_create_person( new_user ) == FAILURE )
    {
	cached_delete_conf( new_user );
	mark_conference_as_changed( new_user ); /*&*/
	return 0;
    }

    if ( ( pers_p = cached_get_person_stat( new_user )) == NULL )
    {
	cached_delete_conf( new_user );
	mark_conference_as_changed( new_user ); /*&*/
	restart_kom("create_person() - can't get pers_stat");
    }

	
    /* Fill in Person */
    if ( do_set_passwd( pers_p->pwd, passwd) != OK )
	restart_kom("create_person(): can't set passwd\n");

646
    pers_p->privileges.change_name = param.default_change_name;
David Byers's avatar
David Byers committed
647
    pers_p->flags = flags;
648

Per Cederqvist's avatar
Per Cederqvist committed
649
650
    mark_person_as_changed( new_user );

651
652
653
654
655
656
657
658
659
660
    mship_type.invitation = 0;
    mship_type.passive = 0;
    mship_type.secret = 0;
    mship_type.reserved1 = 0;
    mship_type.reserved2 = 0;
    mship_type.reserved3 = 0;
    mship_type.reserved4 = 0;
    mship_type.reserved5 = 0;

    do_add_member( new_user, mailbox, new_user, pers_p,
David Byers's avatar
Server  
David Byers committed
661
                   ACTPERS ? ACTPERS : new_user,
David Byers's avatar
David Byers committed
662
                   UCHAR_MAX, 0, &mship_type, FALSE );
Per Cederqvist's avatar
Per Cederqvist committed
663

664
    prepare_aux_item_list(conf_aux, new_user);
665
666
667
668

    if (conf_stat_check_add_aux_item_list(mailbox,
                                          new_user,
                                          conf_aux,
669
670
                                          new_user,
                                          TRUE) != OK)
671
672
673
674
675
676
677
678
679
680
681
682
683
    {
        cached_delete_conf(new_user);
        cached_delete_person(new_user);

        return 0;
    }

    conf_stat_add_aux_item_list(mailbox,
                                new_user,
                                conf_aux,
                                new_user);


Per Cederqvist's avatar
Per Cederqvist committed
684
685
686
687
688
    if ( ACTPERS )
    {
	ACT_P->created_persons++;
	mark_person_as_changed( ACTPERS );
    }
689
    else if (do_auto_login)
Per Cederqvist's avatar
Per Cederqvist committed
690
    {
691
692
	/* Auto login, always visible */
	login (new_user, passwd, FALSE);
Per Cederqvist's avatar
Per Cederqvist committed
693
694
695
696
697
698
    }

    return new_user;
}


699
700
701
702
extern Pers_no
create_person_old(const String name,
                  const String passwd)
{
David Byers's avatar
David Byers committed
703
704
705
706
    Personal_flags flags;

    init_personal_flags(&flags);
    return create_person_generic(name, passwd, NULL, flags, TRUE);
707
708
709
710
711
}

extern Pers_no
create_person(const String name,
              const String passwd,
David Byers's avatar
David Byers committed
712
              Personal_flags flags,
713
714
715
716
              Aux_item_list *conf_aux)
{
    Pers_no     pers;

David Byers's avatar
David Byers committed
717
    pers = create_person_generic(name, passwd, conf_aux, flags, FALSE);
718
719
    if (pers != 0)
    {
720
        /* FIXME: Send asynch message */
721
722
723
724
725
726
727
728
    }

    return pers;
}




Per Cederqvist's avatar
Per Cederqvist committed
729
730
731
/*
 * Get the person status of PERSON.
 */
732

David Byers's avatar
Server  
David Byers committed
733
extern Success
734
735
get_person_stat (Pers_no          person,
                 Person	    * result)
Per Cederqvist's avatar
Per Cederqvist committed
736
737
738
739
740
{
    Person *p_orig;
    Conference *pers_c;
    Access acc;
        
David Byers's avatar
Server  
David Byers committed
741
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
742
743
744
    GET_P_STAT(p_orig, person, FAILURE);
    GET_C_STAT(pers_c, person, FAILURE);
    
David Byers's avatar
Server  
David Byers committed
745
    acc = access_perm (person, pers_c, active_connection);
Per Cederqvist's avatar
Per Cederqvist committed
746
747
748
749
  
    if ( acc == error )
	return FAILURE;

David Byers's avatar
David Byers committed
750
    if ( acc <= none )
Per Cederqvist's avatar
Per Cederqvist committed
751
    {
752
        err_stat = person;
Per Cederqvist's avatar
Per Cederqvist committed
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

    *result = *p_orig;	/* Make a copy of the struct. */
    
    /* The user area is normally secret. */

    if( acc != unlimited )
	result->user_area	= 0;
    
    return OK;
}

/* As get_person_stat, but only return the name if bit 0 in mask is set. */

extern  Success
get_person_stat_old (Pers_no	  person,
771
772
                     int 	  mask,
                     Person	* result)
Per Cederqvist's avatar
Per Cederqvist committed
773
774
775
776
777
{
    Person *p_orig;
    Conference *pers_c;
    Access acc;
        
David Byers's avatar
Server  
David Byers committed
778
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
779
780
781
782
783
    CHK_LOGIN(FAILURE);
    
    GET_P_STAT(p_orig, person, FAILURE);
    GET_C_STAT(pers_c, person, FAILURE);
    
David Byers's avatar
Server  
David Byers committed
784
    acc = access_perm (person, pers_c, active_connection);
Per Cederqvist's avatar
Per Cederqvist committed
785
786
787
788
  
    if ( acc == error )
	return FAILURE;

David Byers's avatar
David Byers committed
789
    if ( acc <= none )
Per Cederqvist's avatar
Per Cederqvist committed
790
    {
791
        err_stat = person;
Per Cederqvist's avatar
Per Cederqvist committed
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

    *result = *p_orig;	/* Make a copy of the struct. */
    
    /* The user area is normally secret. */

    if( acc != unlimited )
	result->user_area	= 0;

    if ( !(mask & 1 ) )
	result->username = EMPTY_STRING;
    
    return OK;
}


/* /// */
extern  Success
get_created_texts(Pers_no       pers_no,
		  Local_text_no first,
		  u_long        len,
815
		  L2g_iterator * result)
Per Cederqvist's avatar
Per Cederqvist committed
816
817
818
819
{
    Person *pers_p;
    Access acc;
    Local_text_no new_first;
820
    Local_text_no new_len;
Per Cederqvist's avatar
Per Cederqvist committed
821

David Byers's avatar
Server  
David Byers committed
822
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
823
824
825
826
    CHK_LOGIN(FAILURE);

    GET_P_STAT(pers_p, pers_no, FAILURE);

David Byers's avatar
Server  
David Byers committed
827
    acc = access_perm(pers_no, NULL, active_connection);
Per Cederqvist's avatar
Per Cederqvist committed
828

829
    if (acc == error)
Per Cederqvist's avatar
Per Cederqvist committed
830
831
	return FAILURE;

David Byers's avatar
David Byers committed
832
    if (acc <= none)
Per Cederqvist's avatar
Per Cederqvist committed
833
    {
834
        err_stat = pers_no;
Per Cederqvist's avatar
Per Cederqvist committed
835
836
837
838
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

839
    new_first = l2g_next_key(&pers_p->created_texts, 0);
840
841
    if (new_first == 0)
	new_first = l2g_first_appendable_key(&pers_p->created_texts);
842
    new_first = max(new_first, first);
Per Cederqvist's avatar
Per Cederqvist committed
843

844
    if (first >= l2g_first_appendable_key(&pers_p->created_texts))
Per Cederqvist's avatar
Per Cederqvist committed
845
    {
846
        err_stat = first;
Per Cederqvist's avatar
Per Cederqvist committed
847
848
849
850
	kom_errno = KOM_NO_SUCH_LOCAL_TEXT;
	return FAILURE;
    }

851
852
    new_len = l2g_first_appendable_key(&pers_p->created_texts) - new_first;
    new_len = min(new_len, len);
853
854
    l2gi_searchsome(result, &pers_p->created_texts, new_first,
		    new_first + new_len);
Per Cederqvist's avatar
Per Cederqvist committed
855
856
857
858
859

    return OK;
}


860
861
862
863
864
865
866
867
868
extern Success
map_created_texts(Pers_no       pers_no,
		  Local_text_no	first_local_no,
		  unsigned long no_of_texts,
		  Text_mapping *result)
{
    Person *pers_p;
    Access acc;

David Byers's avatar
Server  
David Byers committed
869
    CHK_CONNECTION(FAILURE);
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
    if (first_local_no == 0)
    {
	err_stat = first_local_no;
	kom_errno = KOM_LOCAL_TEXT_ZERO;
	return FAILURE;
    }

    if (no_of_texts > 255)
    {
	err_stat = 255;
	kom_errno = KOM_LONG_ARRAY;
	return FAILURE;
    }

    GET_P_STAT(pers_p, pers_no, FAILURE);

David Byers's avatar
Server  
David Byers committed
886
    CHK_CONNECTION(FAILURE);
David Byers's avatar
David Byers committed
887
    CHK_LOGIN(FAILURE);
David Byers's avatar
Server  
David Byers committed
888
    acc = access_perm(pers_no, NULL, active_connection);
889
890
891
892

    if (acc == error)
	return FAILURE;

David Byers's avatar
David Byers committed
893
    if (acc <= none)
894
895
896
897
898
899
900
901
902
903
904
905
906
    {
        err_stat = pers_no;
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

    if (first_local_no >= l2g_first_appendable_key(&pers_p->created_texts))
    {
        err_stat = first_local_no;
	kom_errno = KOM_NO_SUCH_LOCAL_TEXT;
	return FAILURE;
    }

907
    result->first = first_local_no;
908
909
910
911
912
913
914
    result->no_of_texts = no_of_texts;
    result->l2g = &pers_p->created_texts;

    return OK;
}


Per Cederqvist's avatar
Per Cederqvist committed
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

/*
 * Set privilege bits of a person. You must have the wheel bit set
 * to be allowed to do this.
 */
extern Success
set_priv_bits(	Pers_no		person,
		Priv_bits	privileges )
{
    Person *p;
    
    CHK_LOGIN(FAILURE);

    GET_P_STAT(p, person, FAILURE);

David Byers's avatar
Server  
David Byers committed
930
    if ( ENA(wheel, 6) )        /* OK -- In an RPC call */
Per Cederqvist's avatar
Per Cederqvist committed
931
932
933
934
935
936
937
    {
	p->privileges = privileges;
	mark_person_as_changed( person );
	return OK;
    }
    else
    {
938
        err_stat = 0;
Per Cederqvist's avatar
Per Cederqvist committed
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
	kom_errno = KOM_PERM;
	return FAILURE;
    }
}

/*
 * Set password. You may set the password of yourself and all persons that
 * you are supervisor of. OLD_PWD is your password. 
 */
extern Success 
set_passwd (Pers_no	    person,
	    const String   old_pwd,	/* of the one who is changing the pwd,
					   not necessarily the person whose pwd
					   is changed. */
	    const String   new_pwd)	/* of person */
{
    Person *p;
    
David Byers's avatar
Server  
David Byers committed
957
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
958
959
960
961
    CHK_LOGIN(FAILURE);

    GET_P_STAT(p, person, FAILURE);

962
    if ( person != ACTPERS &&
David Byers's avatar
Server  
David Byers committed
963
964
         !ENA(wheel, 7)  &&     /* OK -- In an RPC call */
         !ENA(wheel, 8)  &&     /* OK -- In an RPC call */
965
         !is_supervisor (person, NULL, ACTPERS, ACT_P) )
Per Cederqvist's avatar
Per Cederqvist committed
966
    {
967
        err_stat = person;
Per Cederqvist's avatar
Per Cederqvist committed
968
969
970
971
972
973
	kom_errno = KOM_PERM;
	return FAILURE;	   /* Not allowed to change the other persons pwd */
    }

    if ( chk_passwd( ACT_P->pwd, old_pwd ) == FAILURE )     
    {
974
        err_stat = person;
Per Cederqvist's avatar
Per Cederqvist committed
975
976
977
978
979
980
	kom_errno = KOM_PWD;
	return FAILURE;
    }

    if ( do_set_passwd( p->pwd, new_pwd ) != OK)
    {
981
        err_stat = 0;
Per Cederqvist's avatar
Per Cederqvist committed
982
983
984
985
986
987
988
989
990
991
992
	kom_errno = KOM_PWD;
	return FAILURE;
    }

    mark_person_as_changed( person );

    return OK;
}

/*
 * Ask which texts a person has read in a certain conference.
993
 * Can be done before login. Will return EMPTY_MEMBERSHIP if VICTIM
Per Cederqvist's avatar
Per Cederqvist committed
994
995
996
997
998
999
1000
1001
1002
 * has his unread_is_secret-flag set. This can not be distinguished
 * from the case when VICTIM has not read any texts in CONF_NO. This
 * is a feature, not a bug. (At least I think so. /ceder+++)
 *
 * (*** Well, I've changed my mind. This call is full of security holes.
 *	/ceder)
 *
 * Will fail if VICTIM is not a member of CONF_NO.
 */
1003

David Byers's avatar
David Byers committed
1004
1005
1006
1007
static Success
do_query_read_texts(Pers_no	  victim,
                    Conf_no	  conf_no,
                    Membership * result)
Per Cederqvist's avatar
Per Cederqvist committed
1008
{
Per Cederqvist's avatar
Per Cederqvist committed
1009
    Person	* victim_p;
Per Cederqvist's avatar
Per Cederqvist committed
1010
1011
1012
    Membership  * membp;
    Access	  victim_acc;

David Byers's avatar
Server  
David Byers committed
1013
    CHK_CONNECTION(FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
1014
    GET_P_STAT( victim_p, victim, FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
1015

David Byers's avatar
Server  
David Byers committed
1016
    victim_acc = access_perm(victim, NULL, active_connection);
Per Cederqvist's avatar
Per Cederqvist committed
1017
1018
    if ( victim_acc <= none )
    {
1019
        err_stat = victim;
Per Cederqvist's avatar
Per Cederqvist committed
1020
1021
1022
1023
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

David Byers's avatar
Server  
David Byers committed
1024
    if ( access_perm(conf_no, NULL, active_connection) <= none )
Per Cederqvist's avatar
Per Cederqvist committed
1025
    {
1026
        err_stat = conf_no;
Per Cederqvist's avatar
Per Cederqvist committed
1027
1028
1029
1030
	kom_errno = KOM_UNDEF_CONF;
	return FAILURE;
    }
    
1031
    membp = locate_membership (conf_no, victim_p);
David Byers's avatar
David Byers committed
1032
1033

    if (membp == NULL)
Per Cederqvist's avatar
Per Cederqvist committed
1034
    {
1035
        err_stat = conf_no;
Per Cederqvist's avatar
Per Cederqvist committed
1036
1037
1038
1039
	kom_errno = KOM_NOT_MEMBER;
	return FAILURE;
    }

1040
1041
    if (membp->type.secret &&
        !is_supervisor(victim, NULL, ACTPERS, ACT_P) &&
David Byers's avatar
Server  
David Byers committed
1042
        !ENA(admin, 4))         /* OK -- Guarded */
1043
1044
1045
1046
1047
1048
    {
        err_stat = conf_no;
        kom_errno = KOM_NOT_MEMBER;
        return FAILURE;
    }

Per Cederqvist's avatar
Per Cederqvist committed
1049
1050
    *result = *membp;

Per Cederqvist's avatar
Per Cederqvist committed
1051
    if ( victim_p->flags.unread_is_secret &&
1052
         victim_acc != unlimited)
Per Cederqvist's avatar
Per Cederqvist committed
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
    {
	result->last_time_read = NO_TIME;
	result->last_text_read = 0;
	result->no_of_read = 0;
	result->read_texts = NULL;
    }

    return OK;
}

1063

David Byers's avatar
David Byers committed
1064
1065
1066
extern Success
query_read_texts(Pers_no	  victim,
                 Conf_no	  conf_no,
1067
                 Membership     * result)	/* Points to area to store result in */
David Byers's avatar
David Byers committed
1068
1069
1070
{
    return do_query_read_texts(victim,
                               conf_no,
1071
                               result);
David Byers's avatar
David Byers committed
1072
1073
1074
1075
1076
1077
1078
1079
}


extern Success
query_read_texts_old(Pers_no victim,
                     Conf_no conf_no,
                     Membership *result)
{
1080
    return do_query_read_texts(victim, conf_no, result);
David Byers's avatar
David Byers committed
1081
1082
1083
1084
}



1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
/*
 * Set user_area. The text is a text which has previously been created
 * with create_text(). It typically contains option-settings for the
 * clients, e. g. if you want to be interrupted when new mail arrives.
 * The format of this text is not yet defined.
 *
 * set_user_area(0) to clear the user area.
 */

extern Success
set_user_area(Pers_no	pers_no,
	      Text_no	user_area)
{
    Person *pers_p;
David Byers's avatar
David Byers committed
1099
    Access  acc;
1100

David Byers's avatar
Server  
David Byers committed
1101
    CHK_CONNECTION(FAILURE);
1102
1103
    CHK_LOGIN(FAILURE);

David Byers's avatar
David Byers committed
1104
    GET_P_STAT(pers_p, pers_no, FAILURE);
David Byers's avatar
Server  
David Byers committed
1105
    acc = access_perm(pers_no, NULL, active_connection);
David Byers's avatar
David Byers committed
1106
1107
1108
1109
1110
1111
1112
    if (acc <= none)
    {
        err_stat = pers_no;
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }
    if (acc != unlimited)
1113
    {
1114
        err_stat = pers_no;
1115
1116
1117
1118
1119
1120
	kom_errno = KOM_PERM;
	return FAILURE;
    }

    return do_set_user_area (pers_no, pers_p, user_area);
}
David Byers's avatar
David Byers committed
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133


/*
 * Set the personal flags
 */

extern Success
set_pers_flags(Pers_no pers_no,
               Personal_flags flags)
{
    Person *pers_p;
    Access  acc;

David Byers's avatar
Server  
David Byers committed
1134
    CHK_CONNECTION(FAILURE);
David Byers's avatar
David Byers committed
1135
1136
1137
1138
    CHK_LOGIN(FAILURE);

    GET_P_STAT(pers_p, pers_no, FAILURE);

David Byers's avatar
Server  
David Byers committed
1139
    acc = access_perm(pers_no, NULL, active_connection);
David Byers's avatar
David Byers committed
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
    if (acc <= none)
    {
        err_stat = pers_no;
        kom_errno = KOM_UNDEF_PERS;
        return FAILURE;
    }
    if (acc != unlimited)
    {
        err_stat = pers_no;
	kom_errno = KOM_PERM;
	return FAILURE;
    }

    pers_p->flags = flags;
    mark_person_as_changed(pers_no);

    return OK;
}