1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
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
366
367
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
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
|
/** BEGIN COPYRIGHT BLOCK
* Copyright 2001 Sun Microsystems, Inc.
* Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
* All rights reserved.
* END COPYRIGHT BLOCK **/
/*
* Description (nsumgmt.c)
*
* This module contains routines for managing information in a
* Netscape user database. Information for a particular user
* is modified by retrieving the current information in the form
* of a user object (UserObj_t), calling functions in this module,
* to modify the user object, and then calling userStore() to
* write the information in the user object back to the database.
*/
#include "base/systems.h"
#include "netsite.h"
#include "assert.h"
#include "libaccess/nsdbmgmt.h"
#define __PRIVATE_NSUSER
#include "libaccess/nsumgmt.h"
/*
* Description (userAddGroup)
*
* This function adds a group id to the list of group ids associated
* with a user object.
*
* Arguments:
*
* uoptr - user object pointer
* gid - group id to be added
*
* Returns:
*
* Returns zero if the group id is already present in the group id list.
* Returns one if the group id was added successfully.
* Returns a negative value if an error occurs.
*/
int userAddGroup(UserObj_t * uoptr, USI_t gid)
{
int rv;
rv = usiInsert(&uoptr->uo_groups, gid);
if (rv > 0) {
uoptr->uo_flags |= UOF_MODIFIED;
}
return rv;
}
/*
* Description (userCreate)
*
* This function creates a user object, using information about
* the user provided by the caller. The strings passed for the
* user account name, password, and real user name may be on the
* stack. The user id is set to zero, but the user object is
* marked as being new. A user id will be assigned when
* userStore() is called to add the user to a user database.
*
* Arguments:
*
* name - pointer to user account name string
* pwd - pointer to (encrypted) password string
* rname - real user name (gecos string)
*
* Returns:
*
* A pointer to a dynamically allocated UserObj_t structure is
* returned.
*/
NSAPI_PUBLIC UserObj_t * userCreate(NTS_t name, NTS_t pwd, NTS_t rname)
{
UserObj_t * uoptr; /* user object pointer */
uoptr = (UserObj_t *)MALLOC(sizeof(UserObj_t));
if (uoptr) {
uoptr->uo_name = (NTS_t)STRDUP((char *)name);
uoptr->uo_pwd = (pwd) ? (NTS_t)STRDUP((char *)pwd) : 0;
uoptr->uo_uid = 0;
uoptr->uo_flags = (UOF_MODIFIED | UOF_NEW);
uoptr->uo_rname = (rname) ? (NTS_t)STRDUP((char *)rname) : 0;
UILINIT(&uoptr->uo_groups);
}
return uoptr;
}
/*
* Description (userDeleteGroup)
*
* This function removes a specified group id from a user object's
* list of groups.
*
* Arguments:
*
* uoptr - pointer to user object
* gid - group id to remove
*
* Returns:
*
* The return value is zero if the specified group id was not present
* in the user object, or one if the group was successfully removed.
*/
int userDeleteGroup(UserObj_t * uoptr, USI_t gid)
{
int rv; /* return value */
rv = usiRemove(&uoptr->uo_groups, gid);
if (rv > 0) {
uoptr->uo_flags |= UOF_MODIFIED;
}
return rv;
}
/*
* Description (userEncode)
*
* This function encodes a user object into a user DB record.
*
* Arguments:
*
* uoptr - pointer to user object
* ureclen - pointer to returned record length
* urecptr - pointer to returned record pointer
*
* Returns:
*
* The function return value is zero if successful. The length
* and location of the created attribute record are returned
* through 'ureclen' and 'urecptr'. A non-zero function value
* is returned if there's an error.
*/
int userEncode(UserObj_t * uoptr, int * ureclen, ATR_t * urecptr)
{
int reclen; /* length of DB record */
ATR_t rptr; /* DB record pointer */
ATR_t rstart = 0; /* pointer to beginning of DB record */
ATR_t glptr; /* saved pointer to UAT_GROUPS length */
ATR_t gptr; /* saved pointer to after length at glptr */
int pwdlen; /* password encoding length */
int uidlen; /* uid encoding length */
int fllen; /* account flags encoding length */
USI_t rnlen; /* real name encoding length */
USI_t nglen; /* group count encoding length */
USI_t gcnt; /* number of group ids */
USI_t * gids; /* pointer to array of group ids */
int i; /* group id index */
int rv = -1;
/*
* First we need to figure out how long the generated record will be.
* This doesn't have to be exact, but it must not be smaller than the
* actual record size.
*/
/* UAT_PASSWORD attribute: tag, length, NTS */
pwdlen = NTSLENGTH(uoptr->uo_pwd);
reclen = 1 + 1 + pwdlen;
if (pwdlen > 127) goto punt;
/* UAT_UID attribute: tag, length, USI */
uidlen = USILENGTH(uoptr->uo_uid);
reclen += (1 + 1 + uidlen);
/* UAT_ACCFLAGS attribute: tag, length, USI */
fllen = USILENGTH(uoptr->uo_flags & UOF_DBFLAGS);
reclen += (1 + 1 + fllen);
/* UAT_REALNAME attribute: tag, length, NTS */
rnlen = NTSLENGTH(uoptr->uo_rname);
reclen += (1 + USILENGTH(rnlen) + rnlen);
/* UAT_GROUPS attribute: tag, length, USI(count), USI(gid)... */
gcnt = UILCOUNT(&uoptr->uo_groups);
nglen = USILENGTH(gcnt);
reclen += (1 + USIALLOC() + nglen + (5 * gcnt));
/* Allocate the attribute record buffer */
rptr = (ATR_t)MALLOC(reclen);
if (rptr) {
/* Save pointer to start of record */
rstart = rptr;
/* Encode UAT_PASSWORD attribute */
*rptr++ = UAT_PASSWORD;
*rptr++ = pwdlen;
rptr = NTSENCODE(rptr, uoptr->uo_pwd);
/* Encode UAT_UID attribute */
*rptr++ = UAT_UID;
*rptr++ = uidlen;
rptr = USIENCODE(rptr, uoptr->uo_uid);
/* Encode UAT_ACCFLAGS attribute */
*rptr++ = UAT_ACCFLAGS;
*rptr++ = fllen;
rptr = USIENCODE(rptr, (uoptr->uo_flags & UOF_DBFLAGS));
/* Encode UAT_REALNAME attribute */
*rptr++ = UAT_REALNAME;
rptr = USIENCODE(rptr, rnlen);
rptr = NTSENCODE(rptr, uoptr->uo_rname);
/* Encode UAT_GROUPS attribute */
*rptr++ = UAT_GROUPS;
/*
* Save a pointer to the attribute encoding length, and reserve
* space for the maximum encoding size of a USI_t value.
*/
glptr = rptr;
rptr += USIALLOC();
gptr = rptr;
/* Encode number of groups */
rptr = USIENCODE(rptr, gcnt);
/* Generate group ids encodings */
gids = UILLIST(&uoptr->uo_groups);
for (i = 0; i < gcnt; ++i) {
rptr = USIENCODE(rptr, gids[i]);
}
/* Now fix up the UAT_GROUPS attribute encoding length */
glptr = USIINSERT(glptr, (USI_t)(rptr - gptr));
/* Return record length and location if requested */
if (ureclen) *ureclen = rptr - rstart;
if (urecptr) *urecptr = rstart;
/* Indicate success */
rv = 0;
}
punt:
return rv;
}
/*
* Description (userRemove)
*
* This function is called to remove a user from a specified user
* database. Both the primary DB file and the id-to-name DB file
* are updated.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* userdb - handle for user DB access
* flags - (unused - must be zero)
* name - pointer to user account name
*
* Returns:
*
* If successful, the return value is zero. Otherwise it is a
* non-zero error code.
*/
NSAPI_PUBLIC int userRemove(NSErr_t * errp, void * userdb, int flags, NTS_t name)
{
UserObj_t * uoptr; /* user object pointer */
int rv;
int rv2;
/* First retrieve the user record */
uoptr = userFindByName(errp, userdb, name);
if (!uoptr) {
/* Error - specified user not found */
return NSAERRNAME;
}
/* Free the user id value, if any */
rv = 0;
if (uoptr->uo_uid != 0) {
rv = ndbFreeId(errp, userdb, 0, (char *)name, uoptr->uo_uid);
}
rv2 = ndbDeleteName(errp, userdb, 0, 0, (char *)name);
return (rv) ? rv : rv2;
}
/*
* Description (userRename)
*
* This function is called to change the account name associated
* with an existing user. The caller provides a pointer to a
* user object for the existing user (with the current user account
* name referenced by uo_name), and the new account name for this
* user. A check is made to ensure the uniqueness of the new name
* in the specified user database. The account name in the user
* object is modified. The user database is not modified until
* userStore() is called.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* userdb - handle for user DB access
* uoptr - user object pointer
* newname - pointer to new account name string
*
* Returns:
*
* If successful, the return value is zero. Otherwise it is a
* non-zero error code. The user object remains intact in either
* case.
*/
NSAPI_PUBLIC int userRename(NSErr_t * errp, void * userdb, UserObj_t * uoptr, NTS_t newname)
{
int reclen; /* user record length */
ATR_t recptr = 0; /* user record pointer */
char * oldname; /* old user account name */
int eid; /* error id code */
int rv; /* result value */
/* Save the current account name and replace it with the new one */
oldname = (char *)uoptr->uo_name;
uoptr->uo_name = (unsigned char *) STRDUP((char *)newname);
if ((oldname != 0) && !(uoptr->uo_flags & UOF_NEW)) {
/* Convert the information in the user object to a DB record */
rv = userEncode(uoptr, &reclen, &recptr);
if (rv) goto err_nomem;
/*
* Store the record in the database
* under the new user account name.
*/
rv = ndbStoreName(errp, userdb, NDBF_NEWNAME,
0, (char *)uoptr->uo_name, reclen, (char *)recptr);
if (rv) goto punt;
/* Change the mapping of the user id to the new name */
rv = ndbRenameId(errp, userdb, 0, (char *)uoptr->uo_name, uoptr->uo_uid);
if (rv) goto punt;
/* Delete the user record with the old account name */
rv = ndbDeleteName(errp, userdb, 0, 0, oldname);
if (rv) goto punt;
}
else {
/* Set flags in user object for userStore() */
uoptr->uo_flags |= UOF_MODIFIED;
}
punt:
if (recptr) {
FREE(recptr);
}
if (oldname) {
FREE(oldname);
}
return rv;
err_nomem:
eid = NSAUERR1000;
rv = NSAERRNOMEM;
nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
goto punt;
}
/*
* Description (userStore)
*
* This function is called to store a user object in the database.
* If the object was created by userCreate(), it is assumed to be
* a new user account, the user account name must not match any
* existing user account names in the database, and a uid is
* assigned before adding the user to the database. If the object
* was created by userFindByName(), the information in the user
* object will replace the existing database entry for the
* indicated user account name.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* userdb - handle for user DB access
* flags - (unused - must be zero)
* uoptr - user object pointer
*
* Returns:
*
* If successful, the return value is zero. Otherwise it is a
* non-zero error code. The user object remains intact in either
* case.
*/
NSAPI_PUBLIC int userStore(NSErr_t * errp, void * userdb, int flags, UserObj_t * uoptr)
{
ATR_t recptr = 0;
USI_t uid;
int reclen = 0;
int stflags = 0;
int eid;
int rv;
/* If this is a new user, allocate a uid value */
if (uoptr->uo_flags & UOF_NEW) {
/*
* Yes, allocate a user id and add a user id to user
* account name mapping to the id-to-name DB file.
*/
uid = 0;
rv = ndbAllocId(errp, userdb, 0, (char *)uoptr->uo_name, &uid);
if (rv) goto punt;
uoptr->uo_uid = uid;
/* Let the database manager know that this is a new entry */
stflags = NDBF_NEWNAME;
}
/* Convert the information in the user object to a DB record */
rv = userEncode(uoptr, &reclen, &recptr);
if (rv) goto err_nomem;
/* Store the record in the database under the user account name. */
rv = ndbStoreName(errp, userdb, stflags,
0, (char *)uoptr->uo_name, reclen, (char *)recptr);
if (rv) goto punt;
FREE(recptr);
recptr = 0;
uoptr->uo_flags &= ~(UOF_NEW | UOF_MODIFIED);
return 0;
err_nomem:
eid = NSAUERR1100;
rv = NSAERRNOMEM;
nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
punt:
if (recptr) {
FREE(recptr);
}
if ((uoptr->uo_flags & UOF_NEW) && (uid != 0)) {
/* Free the user id value if we failed after allocating it */
ndbFreeId(errp, userdb, 0, (char *)uoptr->uo_name, uid);
}
return rv;
}
|