person.c 19.9 KB
Newer Older
Linus Tolke's avatar
Linus Tolke committed
1
/*
2
 * $Id: person.c,v 0.29 1994/06/18 20:35:55 ceder Exp $
Per Cederqvist's avatar
Per Cederqvist committed
3
 * Copyright (C) 1991, 1992, 1993, 1994  Lysator Academic Computer Association.
Linus Tolke's avatar
Linus Tolke 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

31
static char *rcsid = "$Id: person.c,v 0.29 1994/06/18 20:35:55 ceder Exp $";
32
33
#include "rcs.h"
USE(rcsid);
Per Cederqvist's avatar
Per Cederqvist committed
34

Per Cederqvist's avatar
Per Cederqvist committed
35
36
#include <limits.h>
#include <stdio.h>
37
38
39
40
41
42
#ifdef HAVE_STDLIB_H
#  include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#  include <string.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
43
44
45
#include <time.h>
#include <unistd.h>		/* for crypt() on Linux */
#include <setjmp.h>
Per Cederqvist's avatar
Per Cederqvist committed
46
#include <sys/types.h>
47
#ifdef HAVE_STDARG_H
Per Cederqvist's avatar
Per Cederqvist committed
48
#    include <stdarg.h>
49
#endif
Per Cederqvist's avatar
Per Cederqvist committed
50

Per Cederqvist's avatar
Per Cederqvist committed
51
52
53
54
#include "misc-types.h"
#include "s-string.h"
#include "kom-types.h"
#include "services.h"
Per Cederqvist's avatar
Per Cederqvist committed
55
#include "manipulate.h"
Per Cederqvist's avatar
Per Cederqvist committed
56
#include "string-malloc.h"
Per Cederqvist's avatar
Per Cederqvist committed
57
#include "debug.h"
Per Cederqvist's avatar
Per Cederqvist committed
58
#include "cache.h"
Per Cederqvist's avatar
Per Cederqvist committed
59
#include "kom-errno.h"
Per Cederqvist's avatar
Per Cederqvist committed
60
61
#include "com.h"
#include "connections.h"
Per Cederqvist's avatar
Per Cederqvist committed
62
63
64
65
66
#include "server/smalloc.h"
#include "config.h"
#include "log.h"
#include "minmax.h"
#include "lyskomd.h"
67
#include "param.h"
68

Per Cederqvist's avatar
Per Cederqvist committed
69
70
71
/*
 * Static functions.
 */
72

Per Cederqvist's avatar
Per Cederqvist committed
73
74
75
static Bool
legal_passwd(const String pwd)
{
76
77
78
79
80
81
82
    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
83
84
85
86
87
88
}

static Success
do_set_passwd( Password        pwd,
	       const String   new_pwd)
{
Per Cederqvist's avatar
Per Cederqvist committed
89
90
#ifdef ENCRYPT_PASSWORDS
    char salt[3];
Per Cederqvist's avatar
Per Cederqvist committed
91
92
    static char crypt_seed[] = 
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
93
    char *password;
Per Cederqvist's avatar
Per Cederqvist committed
94

Per Cederqvist's avatar
Per Cederqvist committed
95
96
    if ( !legal_passwd(new_pwd) )
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
97

98
99
    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
100
    salt[2] = '\0';
101
102
103
104
105
106
107

    password = s_crea_c_str(new_pwd);
    if (password == NULL)
	return FAILURE;
    else
    {
	strcpy((char *)pwd, (const char *)crypt(password, salt));
108
	string_free(password);
109
110
	return OK;
    }
Per Cederqvist's avatar
Per Cederqvist committed
111
112
113
114
115
116
117
118

#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
119
120
    strncpy(pwd, (const char *)new_pwd.string,
	    min( PASSWD_LEN-1, new_pwd.len ));
Per Cederqvist's avatar
Per Cederqvist committed
121

Per Cederqvist's avatar
Per Cederqvist committed
122
    return OK;
123
124

#endif
Per Cederqvist's avatar
Per Cederqvist committed
125
126
127
128
129
130
}



/*
 * Mark a text. No check is done if pers_p is really allowed to mark it.
131
132
 * 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
 */

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;
    BUGDECL;

    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;
    }

160
    if (old_mark != NULL)
Per Cederqvist's avatar
Per Cederqvist committed
161
162
163
164
165
166
167
168
    {
	/* 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);
    }
169
170
171
172
173
174
175
176
    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);

177
178
	if (text_s->no_of_marks >= param.max_marks_text
	    || pers_p->marks.no_of_marks >= param.max_marks_person)
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
	{
	    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;
    BUGDECL;

    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
225
226
    {
	/* Delete this mark. */
227
	BUG(("do_unmark_text(): Delete mark.\n"));
Per Cederqvist's avatar
Per Cederqvist committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
	
	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 )
	    {
245
		log("WNG: do_unmark_text(): Text %d has no_of_marks==0,\
Per Cederqvist's avatar
Per Cederqvist committed
246
247
248
249
250
251
252
253
254
255
256
257
258
 		     but person %d had marked the text.",
		    text_no, pers_no);
	    }
	    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
    {
259
260
261
262
	/* An attempt to delete a non-existent mark. */
	BUG(("do_unmark_text(): delete non-existent mark.\n"));
	kom_errno = KOM_NOT_MARKED;
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
263
264
265
266
267
268
269
270
271
272
273
274
275
    }
    
    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,
276
277
		 Person	   * pers_p, /* May be NULL */
		 Text_no     user_area)
Per Cederqvist's avatar
Per Cederqvist committed
278
279
280
281
{
    Text_stat * old_user_area;
    Text_stat * new_user_area = NULL; /* To stop gcc complaining. */

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

284
    if ( user_area != 0 )
Per Cederqvist's avatar
Per Cederqvist committed
285
    {
286
	GET_T_STAT(new_user_area, user_area, FAILURE);
287
	if ( new_user_area->no_of_marks >= param.max_marks_text )
Per Cederqvist's avatar
Per Cederqvist committed
288
	{
Per Cederqvist's avatar
Per Cederqvist committed
289
290
	    log("%s(%d, %d): New user_area's mark count (%d) > %d.\n",
		"LIMIT: set_user_area",
291
		pers_no, user_area, new_user_area->no_of_marks,
292
		param.max_marks_text);
293
	    kom_errno = KOM_MARK_LIMIT;
Per Cederqvist's avatar
Per Cederqvist committed
294
295
296
	    return FAILURE;
	}
    }
297
298
299

    if ( pers_p == NULL )
	GET_P_STAT(pers_p, pers_no, FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
300
301
302
303
    
    /* Unmark the previous user_area if it exists. */

    if ( pers_p->user_area != 0
304
	&& (old_user_area = cached_get_text_stat(pers_p->user_area)) != NULL)
Per Cederqvist's avatar
Per Cederqvist committed
305
306
307
308
    {
	if ( old_user_area->no_of_marks > 0 )
	{
	    --old_user_area->no_of_marks;
309
	    mark_text_as_changed( pers_p->user_area );
Per Cederqvist's avatar
Per Cederqvist committed
310
311
312
	}
	else
	{
313
314
	    log("ERROR: set_user_area(%d, %d): Old user_area %d not marked\n",
		pers_no, user_area, pers_p->user_area);
Per Cederqvist's avatar
Per Cederqvist committed
315
316
317
318
319
	}
    }

    /* Mark the new user_area */

320
    if ( user_area != 0 )
Per Cederqvist's avatar
Per Cederqvist committed
321
322
    {
	++new_user_area->no_of_marks;
323
	mark_text_as_changed( user_area );
Per Cederqvist's avatar
Per Cederqvist committed
324
325
    }
    
326
327
    pers_p->user_area = user_area;
    mark_person_as_changed (pers_no);
Per Cederqvist's avatar
Per Cederqvist committed
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

    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)
	{
	    log("ERROR: do_delete_pers(): can't sub_member\n");
	}
    }

    for ( i = pers_p->marks.no_of_marks; i > 0; i-- )
    {
366
367
	if ( do_unmark_text(pers_no, pers_p,
			    pers_p->marks.marks[0].text_no, NULL) != OK )
Per Cederqvist's avatar
Per Cederqvist committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
	{
	    log("WNG: do_delete_pers(): can't unmark text %d (i == %d)\n",
		pers_p->marks.marks[0].text_no, i);
	}
    }
    
    if ( do_set_user_area(pers_no, pers_p, 0) != OK )
    {
	log("WNG: do_delete_pers(): can't unmark user_area\n");
    }

    s_clear( &pers_p->username );
    sfree( pers_p->created_texts.texts );
    pers_p->created_texts.texts = NULL;
    pers_p->created_texts.no_of_texts = 0;

    cached_delete_person(pers_no);
    /* ??? Eller r{cker det med cached_delete_conf() ??? */
    
    /* ASYNC */
    return OK;    
}

/*
 * Check a password
 */
Success
Per Cederqvist's avatar
Per Cederqvist committed
395
396
chk_passwd (Password      pwd,
	    const String  try)
Per Cederqvist's avatar
Per Cederqvist committed
397
{
Per Cederqvist's avatar
Per Cederqvist committed
398
#ifdef ENCRYPT_PASSWORDS
399
    char *c_try;
Per Cederqvist's avatar
Per Cederqvist committed
400

401
402
403
404
    c_try = s_crea_c_str(try);
    if (c_try == NULL)
	return FAILURE;
    
Per Cederqvist's avatar
Per Cederqvist committed
405
    if (strcmp ((const char *)pwd,
406
407
		(const char *)crypt(c_try, (const char *)pwd)) != 0)
    {
408
	string_free(c_try);
Per Cederqvist's avatar
Per Cederqvist committed
409
	return FAILURE;
410
    }
Per Cederqvist's avatar
Per Cederqvist committed
411
    else
412
    {
413
	string_free(c_try);
Per Cederqvist's avatar
Per Cederqvist committed
414
	return OK;
415
    }
Per Cederqvist's avatar
Per Cederqvist committed
416
417
418

#else

Per Cederqvist's avatar
Per Cederqvist committed
419
420
    int i;
    
Per Cederqvist's avatar
Per Cederqvist committed
421
    if ( try.len != *pwd )
Per Cederqvist's avatar
Per Cederqvist committed
422
423
	return FAILURE;

Per Cederqvist's avatar
Per Cederqvist committed
424
425
    for ( i = 0; i < try.len; i++ )
	if ( pwd[ i + 1 ] != try.string[ i ] )
Per Cederqvist's avatar
Per Cederqvist committed
426
427
428
	    return FAILURE;

    return OK;
Per Cederqvist's avatar
Per Cederqvist committed
429
430

#endif
Per Cederqvist's avatar
Per Cederqvist committed
431
432
433
434
435
436
437
438
439
440
441
442
443
444
}


/*
 * 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
445
446
447
448
449
450
451
452
453
454
455
456
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
457
458
459
460
461
462
{
    Text_stat *text_s = NULL;
    BUGDECL;
        
    CHK_LOGIN(FAILURE);

463
464
465
    /* Check that the user is allowed to read the text. */
    GET_T_STAT(text_s, text_no, FAILURE);
    if ( !text_read_access(text_no, text_s) )
Per Cederqvist's avatar
Per Cederqvist committed
466
    {
467
468
	kom_errno = KOM_PERM;
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
469
470
    }

471
    BUG(("Person %d markerar text %lu med typ %d\n",
Per Cederqvist's avatar
Per Cederqvist committed
472
473
474
475
476
	 ACTPERS, text_no, mark_type));
    
    return do_mark_text(ACTPERS, ACT_P, text_no, text_s, mark_type);
}

477
478
479
480
481
482
483
extern Success
unmark_text(Text_no text_no)
{
    Text_stat *text_s = NULL;
    BUGDECL;
        
    CHK_LOGIN(FAILURE);
484
    BUG(("Person %d avmarkerar text %lu\n", ACTPERS, text_no));
485
486
487
488
    
    return do_unmark_text(ACTPERS, ACT_P, text_no, text_s);
}

Per Cederqvist's avatar
Per Cederqvist committed
489
490
491
/*
 * Create a new person.
 *
492
 * If parameter ``Anyone can create new persons'' is true
Per Cederqvist's avatar
Per Cederqvist committed
493
 * anyone can create themself. Otherwise you must be logged in to
494
495
 * 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
496
497
498
499
500
501
502
503
504
 *
 * 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.
 *
505
506
507
 * 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
508
509
510
511
512
513
514
515
516
517
518
519
520
 *
 * This function returns the Pers_no of the new person, or 0 if an error
 * occured. (0 is an illegal Pers_no).
 */
extern Pers_no
create_person (String         name,
	       const String  passwd )
{
    Pers_no 	  new_user;
    Conference	* mailbox;
    Person	* pers_p;
    

521
    if (ACTPERS == 0)
Per Cederqvist's avatar
Per Cederqvist committed
522
    {
523
524
525
526
527
528
529
530
531
532
533
534
535
536
	if (!param.create_person_before_login && ACTPERS == 0 )
	{
	    kom_errno = KOM_LOGIN;
	    return 0;
	}
    }
    else
    {
	if (param.anyone_can_create_new_persons == FALSE
	    && !ENA(create_pers, 0) )
	{
	    kom_errno = KOM_PERM;
	    return 0;
	}
Per Cederqvist's avatar
Per Cederqvist committed
537
538
539
540
541
542
543
544
545
546
547
548
    }

#if 0
    if ( !logins_allowed  && !ACTPERS ) /* A new user can't create himself */
    {					/* if he isn't allowed to login. */
	kom_errno = KOM_LOGIN_DISALLOWED;
	return 0;
    }
#endif

    if ( !legal_name( name ) )
    {
549
	/* kom_errno will be set by legal_name(). */
Per Cederqvist's avatar
Per Cederqvist committed
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
	return 0;
    }

    if ( !unique_name( name, 0 ) )
    {
	kom_errno = KOM_CONF_EXISTS;
	return 0;
    }

    if ( !legal_passwd( passwd ) )
    {
	kom_errno = KOM_PWD;
	return 0;
    }

    new_user = cached_create_conf( name );

    if ( (mailbox = cached_get_conf_stat( new_user ) ) == NULL)
    {
	restart_kom("create_person() - can't get conf_stat");
    }
    
    
    mailbox->creator		= ACTPERS ? ACTPERS : new_user;
    mailbox->creation_time 	= time(NULL);
    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;
    mailbox->last_written	= mailbox->creation_time;
    mailbox->msg_of_day		= 0;
585
    mailbox->nice		= param.default_nice;
Per Cederqvist's avatar
Per Cederqvist committed
586

587
    mark_conference_as_changed (new_user);
Per Cederqvist's avatar
Per Cederqvist committed
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

    /* 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");

610
611
    pers_p->privileges.change_name = param.default_change_name;

Per Cederqvist's avatar
Per Cederqvist committed
612
613
614
615
616
617
618
619
620
621
622
    mark_person_as_changed( new_user );

    do_add_member( new_user, mailbox, new_user, pers_p, UCHAR_MAX, 0 );

    if ( ACTPERS )
    {
	ACT_P->created_persons++;
	mark_person_as_changed( ACTPERS );
    }
    else
    {
623
624
	/* Auto login, always visible */
	login (new_user, passwd, FALSE);
Per Cederqvist's avatar
Per Cederqvist committed
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
    }

    return new_user;
}


/*
 * Get the person status of PERSON.
 */
extern  Success
get_person_stat (Pers_no	  person,
 		 Person		* result)
{
    Person *p_orig;
    Conference *pers_c;
    Access acc;
        
    GET_P_STAT(p_orig, person, FAILURE);
    GET_C_STAT(pers_c, person, FAILURE);
    
645
    acc = access_perm (person, pers_c, ACTPERS, ACT_P);
Per Cederqvist's avatar
Per Cederqvist committed
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  
    if ( acc == error )
	return FAILURE;

    if ( acc == none )
    {
	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,
		     int 	  mask,
		     Person	* result)
{
    Person *p_orig;
    Conference *pers_c;
    Access acc;
        
    CHK_LOGIN(FAILURE);
    
    GET_P_STAT(p_orig, person, FAILURE);
    GET_C_STAT(pers_c, person, FAILURE);
    
682
    acc = access_perm (person, pers_c, ACTPERS, ACT_P);
Per Cederqvist's avatar
Per Cederqvist committed
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  
    if ( acc == error )
	return FAILURE;

    if ( acc == none )
    {
	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,
		  Text_list   * result)
{
    Person *pers_p;
    Access acc;
    Local_text_no new_first;

    CHK_LOGIN(FAILURE);

    GET_P_STAT(pers_p, pers_no, FAILURE);

722
    acc = access_perm(pers_no, NULL, ACTPERS, ACT_P);
Per Cederqvist's avatar
Per Cederqvist committed
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

    if ( acc == error )
	return FAILURE;

    if ( acc == none )
    {
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

    *result = pers_p->created_texts;
    new_first = max(result->first_local_no, first);

    if ( new_first >= result->first_local_no + result->no_of_texts)
    {
	kom_errno = KOM_NO_SUCH_LOCAL_TEXT;
	return FAILURE;
    }

    result->texts += new_first - result->first_local_no;
    result->no_of_texts = min(len, (result->no_of_texts
				    - (new_first - result->first_local_no)));
    result->first_local_no = new_first;

    return OK;
}



/*
 * 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);

    if ( ENA(wheel, 6) )
    {
	p->privileges = privileges;
	mark_person_as_changed( person );
	return OK;
    }
    else
    {
	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;
    
    CHK_LOGIN(FAILURE);

    GET_P_STAT(p, person, FAILURE);

    if ( person != ACTPERS && !ENA(wheel, 7)
797
	&& !is_supervisor (person, NULL, ACTPERS, ACT_P) )
Per Cederqvist's avatar
Per Cederqvist committed
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
    {
	kom_errno = KOM_PERM;
	return FAILURE;	   /* Not allowed to change the other persons pwd */
    }

    if ( chk_passwd( ACT_P->pwd, old_pwd ) == FAILURE )     
    {
	kom_errno = KOM_PWD;
	return FAILURE;
    }

    if ( do_set_passwd( p->pwd, new_pwd ) != OK)
    {
	kom_errno = KOM_PWD;
	return FAILURE;
    }

    mark_person_as_changed( person );

    return OK;
}

/*
 * Ask which texts a person has read in a certain conference.
 * Can be done before loggin. Will return EMPTY_MEMBERSHIP if VICTIM
 * 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.
 */
extern Success
query_read_texts(Pers_no	  victim,
		 Conf_no	  conf_no,
		 Membership * result)	/* Points to area to store result in */
{
Per Cederqvist's avatar
Per Cederqvist committed
837
    Person	* victim_p;
Per Cederqvist's avatar
Per Cederqvist committed
838
839
840
    Membership  * membp;
    Access	  victim_acc;

Per Cederqvist's avatar
Per Cederqvist committed
841
    GET_P_STAT( victim_p, victim, FAILURE);
Per Cederqvist's avatar
Per Cederqvist committed
842

843
    victim_acc = access_perm(victim, NULL, ACTPERS, ACT_P);
Per Cederqvist's avatar
Per Cederqvist committed
844
845
846
847
848
849
    if ( victim_acc <= none )
    {
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

850
    if ( access_perm(conf_no, NULL, ACTPERS, ACT_P) <= none )
Per Cederqvist's avatar
Per Cederqvist committed
851
852
853
854
855
    {
	kom_errno = KOM_UNDEF_CONF;
	return FAILURE;
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
856
    if ( (membp = locate_membership (conf_no, victim_p)) == NULL)
Per Cederqvist's avatar
Per Cederqvist committed
857
858
859
860
861
862
863
    {
	kom_errno = KOM_NOT_MEMBER;
	return FAILURE;
    }

    *result = *membp;

Per Cederqvist's avatar
Per Cederqvist committed
864
    if ( victim_p->flags.unread_is_secret &&
Per Cederqvist's avatar
Per Cederqvist committed
865
866
867
868
869
870
871
872
873
874
875
	victim_acc != unlimited)
    {
	result->last_time_read = NO_TIME;
	result->last_text_read = 0;
	result->no_of_read = 0;
	result->read_texts = NULL;
    }

    return OK;
}

876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894

/*
 * 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;

    CHK_LOGIN(FAILURE);
    GET_P_STAT(pers_p, pers_no, FAILURE);

895
    if ( access_perm(pers_no, NULL, ACTPERS, ACT_P) != unlimited )
896
897
898
899
900
901
902
    {
	kom_errno = KOM_PERM;
	return FAILURE;
    }

    return do_set_user_area (pers_no, pers_p, user_area);
}