There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.12 - (show annotations) (download) (as text)
Fri Aug 5 11:49:45 2011 UTC (6 months ago) by gneumann
Branch: MAIN
CVS Tags: HEAD
Branch point for: aolserver_v45_r2
Changes since 1.11: +6 -2 lines
File MIME type: text/x-chdr
Patches mostly from Maurizio Martignano
- changed types of file descriptors for socket from "int" to "SOCKET"
- some more _WIN32 cleanups
- defined macro INT2PTR() like in tclInt.h for uniform conversion from "int" to pointers
- minor cleanups for unix using INT2PTR (more similar occurences still to do)
1 /*
2 * The contents of this file are subject to the AOLserver Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://aolserver.com/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30 /*
31 * nsperm --
32 *
33 * Permissions
34 */
35
36 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsperm/nsperm.c,v 1.12 2011/08/05 11:49:45 gneumann Exp $, compiled: " __DATE__ " " __TIME__;
37
38 #include "ns.h"
39
40 #ifndef INADDR_NONE
41 #define INADDR_NONE (-1)
42 #endif
43
44 /*
45 * The following structure is allocated for each instance of the module.
46 */
47
48 typedef struct Server {
49 char *server;
50 Tcl_HashTable users;
51 Tcl_HashTable groups;
52 Ns_RWLock lock;
53 } Server;
54
55 /*
56 * The "users" hash table points to this kind of data:
57 */
58
59 typedef struct {
60 char pass[16];
61 Tcl_HashTable groups;
62 Tcl_HashTable nets;
63 Tcl_HashTable masks;
64 Tcl_HashTable hosts;
65 int filterallow;
66 } User;
67
68 /*
69 * The "groups" hash table points to this kind of data:
70 */
71
72 typedef struct {
73 Tcl_HashTable users;
74 } Group;
75
76 /*
77 * The urlspecific data referenced by uskey hold pointers to these:
78 */
79
80 typedef struct {
81 char *baseurl;
82 Tcl_HashTable allowuser;
83 Tcl_HashTable denyuser;
84 Tcl_HashTable allowgroup;
85 Tcl_HashTable denygroup;
86 int implicit_allow;
87 } Perm;
88
89 /*
90 * Local functions defined in this file
91 */
92
93 static Tcl_CmdProc <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_PermCmd">PermCmd</a>;
94 static int <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>(Tcl_Interp *interp, void *arg);
95 static int <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddUserCmd">AddUserCmd</a>(Server *servPtr, Tcl_Interp *interp,
96 int argc, char **argv);
97 static int <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddGroupCmd">AddGroupCmd</a>(Server *servPtr, Tcl_Interp *interp,
98 int argc, char **argv);
99 static int <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(Server *servPtr, Tcl_Interp *interp,
100 int argc, char **argv, int allow, int user);
101
102 static int <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_ValidateUserAddr">ValidateUserAddr</a>(User *userPtr, char *peer);
103 static int <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AuthProc">AuthProc</a>(char *server, char *method, char *url, char *user,
104 char *pass, char *peer);
105
106 /*
107 * Static variables defined in this file.
108 */
109
110 static int uskey = -1;
111 static Tcl_HashTable serversTable;
112
113
114 /*
115 *----------------------------------------------------------------------
116 *
117 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_NsPerm_ModInit">NsPerm_ModInit</a> --
118 *
119 * Initialize the perms module
120 *
121 * Results:
122 * NS_OK/NS_ERROR
123 *
124 * Side effects:
125 * Init hash table, add tcl commands.
126 *
127 *----------------------------------------------------------------------
128 */
129
130 int
131 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_NsPerm_ModInit">NsPerm_ModInit</a>(char *server, char *module)
132 {
133 Server *servPtr;
134 char *path;
135 Tcl_HashEntry *hPtr;
136 int new;
137
138 if (uskey < 0) {
139 uskey = <a href="/cvs/aolserver/aolserver/nsd/urlspace.c#A_Ns_UrlSpecificAlloc">Ns_UrlSpecificAlloc</a>();
140 Tcl_InitHashTable(&serversTable, TCL_STRING_KEYS);
141 }
142 servPtr = ns_malloc(sizeof(Server));
143 servPtr->server = server;
144 path = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetPath">Ns_ConfigGetPath</a>(server, module, NULL);
145 Tcl_InitHashTable(&servPtr->users, TCL_STRING_KEYS);
146 Tcl_InitHashTable(&servPtr->groups, TCL_STRING_KEYS);
147 Ns_RWLockInit(&servPtr->lock);
148 <a href="/cvs/aolserver/aolserver/nsd/auth.c#A_Ns_SetRequestAuthorizeProc">Ns_SetRequestAuthorizeProc</a>(server, <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AuthProc">AuthProc</a>);
149 <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclInitInterps">Ns_TclInitInterps</a>(server, <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>, servPtr);
150 hPtr = Tcl_CreateHashEntry(&serversTable, server, &new);
151 Tcl_SetHashValue(hPtr, servPtr);
152 return NS_OK;
153 }
154
155
156 /*
157 *----------------------------------------------------------------------
158 *
159 * <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a> --
160 *
161 * Add tcl commands for perms
162 *
163 * Results:
164 * NS_OK
165 *
166 * Side effects:
167 * Adds tcl commands
168 *
169 *----------------------------------------------------------------------
170 */
171
172 static int
173 <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>(Tcl_Interp *interpermPtr, void *arg)
174 {
175 Tcl_CreateCommand(interpermPtr, "ns_perm", <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_PermCmd">PermCmd</a>, arg, NULL);
176 return NS_OK;
177 }
178
179
180 /*
181 *----------------------------------------------------------------------
182 *
183 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_PermCmd">PermCmd</a> --
184 *
185 * The ns_perm tcl command
186 *
187 * Results:
188 * Std tcl ret val
189 *
190 * Side effects:
191 * Yes.
192 *
193 *----------------------------------------------------------------------
194 */
195
196 static int
197 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_PermCmd">PermCmd</a>(ClientData arg, Tcl_Interp *interp, int argc, CONST char **argv)
198 {
199 Server *servPtr = arg;
200 int status;
201
202 if (argc < 2) {
203 Tcl_AppendResult(interp, "wrong # args: should be \"",
204 argv[0], " command ?args ...?\"", NULL);
205 return TCL_ERROR;
206 }
207 Ns_RWLockWrLock(&servPtr->lock);
208 if (STREQ(argv[1], "adduser")) {
209 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddUserCmd">AddUserCmd</a>(servPtr, interp, argc, (char**)argv);
210 } else if (STREQ(argv[1], "addgroup")) {
211 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddGroupCmd">AddGroupCmd</a>(servPtr, interp, argc, (char**)argv);
212 } else if (STREQ(argv[1], "allowuser")) {
213 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(servPtr, interp, argc, (char**)argv, 1, 1);
214 } else if (STREQ(argv[1], "denyuser")) {
215 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(servPtr, interp, argc, (char**)argv, 0, 1);
216 } else if (STREQ(argv[1], "allowgroup")) {
217 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(servPtr, interp, argc, (char**)argv, 1, 0);
218 } else if (STREQ(argv[1], "denygroup")) {
219 status = <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(servPtr, interp, argc, (char**)argv, 0, 0);
220 } else {
221 Tcl_AppendResult(interp, "unknown command \"",
222 argv[1],
223 "\": should be adduser, addgroup, ",
224 "allowuser, denyuser, "
225 "allowgroup, or denygroup", NULL);
226 status = TCL_ERROR;
227 }
228 Ns_RWLockUnlock(&servPtr->lock);
229 return status;
230 }
231
232
233 /*
234 *----------------------------------------------------------------------
235 *
236 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AuthProc">AuthProc</a> --
237 *
238 * Authorize a URL--this callback is called when a new
239 * connection is recieved
240 *
241 * Results:
242 * NS_OK: accept;
243 * NS_FORBIDDEN or NS_UNAUTHORIZED: go away;
244 * NS_ERROR: oops
245 *
246 * Side effects:
247 * None
248 *
249 *----------------------------------------------------------------------
250 */
251
252 static int
253 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AuthProc">AuthProc</a>(char *server, char *method, char *url, char *user, char *pass,
254 char *peer)
255 {
256 Server *servPtr;
257 Perm *permPtr;
258 User *userPtr;
259 Tcl_HashEntry *hPtr;
260 Tcl_HashSearch search;
261 int status;
262 char *group, buf[16];
263
264 if (user == NULL) {
265 user = "";
266 }
267 if (pass == NULL) {
268 pass = "";
269 }
270 hPtr = Tcl_FindHashEntry(&serversTable, server);
271 if (hPtr == NULL) {
272 return NS_FORBIDDEN;
273 }
274 servPtr = Tcl_GetHashValue(hPtr);
275
276 Ns_RWLockRdLock(&servPtr->lock);
277 permPtr = <a href="/cvs/aolserver/aolserver/nsd/urlspace.c#A_Ns_UrlSpecificGet">Ns_UrlSpecificGet</a>(server, method, url, uskey);
278 if (permPtr == NULL) {
279 status = NS_OK;
280 goto done;
281 }
282
283 /*
284 * The first checks below deny access.
285 */
286
287 status = NS_UNAUTHORIZED;
288
289 /*
290 * Verify user password (if any).
291 */
292
293 hPtr = Tcl_FindHashEntry(&servPtr->users, user);
294 if (hPtr == NULL) {
295 goto done;
296 }
297 userPtr = Tcl_GetHashValue(hPtr);
298 if (userPtr->pass[0] != 0) {
299 if (pass[0] == 0) {
300 goto done;
301 }
302 <a href="/cvs/aolserver/aolserver/nsd/crypt.c#A_Ns_Encrypt">Ns_Encrypt</a>(pass, userPtr->pass, buf);
303 if (!STREQ(userPtr->pass, buf)) {
304 goto done;
305 }
306 }
307
308 /*
309 * Check for a vaild user address.
310 */
311
312 if (!<a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_ValidateUserAddr">ValidateUserAddr</a>(userPtr, peer)) {
313 /*
314 * Null user never gets forbidden--give a chance to enter password.
315 */
316 deny:
317 if (*user != '\0') {
318 status = NS_FORBIDDEN;
319 }
320 goto done;
321 }
322
323 /*
324 * Check user deny list.
325 */
326
327 if (Tcl_FindHashEntry(&permPtr->denyuser, user) != NULL) {
328 goto deny;
329 }
330
331 /*
332 * Loop over all groups in this perm record, and then
333 * see if the user is in any of those groups.
334 */
335
336 hPtr = Tcl_FirstHashEntry(&permPtr->denygroup, &search);
337 while (hPtr != NULL) {
338 group = Tcl_GetHashKey(&permPtr->denygroup, hPtr);
339 if (Tcl_FindHashEntry(&userPtr->groups, group) != NULL) {
340 goto deny;
341 }
342 hPtr = Tcl_NextHashEntry(&search);
343 }
344
345 /*
346 * Valid checks below allow access.
347 */
348
349 status = NS_OK;
350
351 /*
352 * Check the allow lists, starting with users
353 */
354
355 if (Tcl_FindHashEntry(&permPtr->allowuser, user) != NULL) {
356 goto done;
357 }
358
359 /*
360 * Loop over all groups in this perm record, and then
361 * see if the user is in any of those groups.
362 */
363
364 hPtr = Tcl_FirstHashEntry(&permPtr->allowgroup, &search);
365 while (hPtr != NULL) {
366 group = Tcl_GetHashKey(&permPtr->allowgroup, hPtr);
367 if (Tcl_FindHashEntry(&userPtr->groups, group) != NULL) {
368 goto done;
369 }
370 hPtr = Tcl_NextHashEntry(&search);
371 }
372
373 /*
374 * Checks above failed. If implicit allow is not set,
375 * change the status back to unauthorized.
376 */
377
378 if (!permPtr->implicit_allow) {
379 status = NS_UNAUTHORIZED;
380 }
381
382 done:
383 Ns_RWLockUnlock(&servPtr->lock);
384 return status;
385 }
386
387
388 /*
389 *----------------------------------------------------------------------
390 *
391 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_ValidateUserAddr">ValidateUserAddr</a> --
392 *
393 * Validate that the peer address is valid for this user
394 *
395 * Results:
396 * NS_TRUE if allowed, NS_FALSE if not
397 *
398 * Side effects:
399 * None
400 *
401 *----------------------------------------------------------------------
402 */
403
404 static int
405 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_ValidateUserAddr">ValidateUserAddr</a>(User *userPtr, char *peer)
406 {
407 struct in_addr peerip, ip, mask;
408 int retval;
409 Tcl_HashSearch search;
410 Tcl_HashEntry *hPtr, *entryPtr;
411
412 if (peer == NULL) {
413 return NS_TRUE;
414 }
415
416 peerip.s_addr = inet_addr(peer);
417 if (peerip.s_addr == INADDR_NONE) {
418 return NS_FALSE;
419 }
420
421 /*
422 * Loop over each netmask, AND the peer address with it,
423 * then see if that address is in the list.
424 */
425
426 hPtr = Tcl_FirstHashEntry(&userPtr->masks, &search);
427 while (hPtr != NULL) {
428 mask.s_addr = (unsigned long) Tcl_GetHashKey(&userPtr->masks, hPtr);
429 ip.s_addr = peerip.s_addr & mask.s_addr;
430
431 /*
432 * There is a potential match. Now make sure it works with the
433 * right address's mask.
434 */
435
436 entryPtr = Tcl_FindHashEntry(&userPtr->nets, (char *) ip.s_addr);
437 if (entryPtr != NULL && mask.s_addr == (unsigned long) Tcl_GetHashValue(entryPtr)) {
438 if (userPtr->filterallow) {
439 return NS_TRUE;
440 } else {
441 return NS_FALSE;
442 }
443 }
444 hPtr = Tcl_NextHashEntry(&search);
445 }
446
447 if (userPtr->filterallow) {
448 retval = NS_FALSE;
449 } else {
450 retval = NS_TRUE;
451 }
452 if (userPtr->hosts.numEntries > 0) {
453 Ns_DString addr;
454
455 /*
456 * If we have gotten this far, it's necessary to do a
457 * reverse dns lookup and try to make a decision
458 * based on that, if possible.
459 */
460
461 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&addr);
462 if (<a href="/cvs/aolserver/aolserver/nsd/dns.c#A_Ns_GetHostByAddr">Ns_GetHostByAddr</a>(&addr, peer) == NS_TRUE) {
463 char *start = addr.string;
464
465 /*
466 * If the hostname is blah.aol.com, check the hash table
467 * for:
468 *
469 * blah.aol.com
470 * .aol.com
471 * .com
472 *
473 * Break out of the loop as soon as a match is found or
474 * all possibilities are exhausted.
475 */
476
477 while (start != NULL && start[0] != '\0') {
478 char *last;
479
480 last = start;
481 hPtr = Tcl_FindHashEntry(&userPtr->hosts, start);
482 if (hPtr != NULL) {
483 if (userPtr->filterallow) {
484 retval = NS_TRUE;
485 } else {
486 retval = NS_FALSE;
487 }
488 break;
489 }
490 start = strchr(start+1, '.');
491 if (start == NULL) {
492 break;
493 }
494 if (last == start) {
495 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Warning, "nsperm: "
496 "invalid hostname '%s'", addr.string);
497 break;
498 }
499 }
500 }
501 }
502
503 return retval;
504 }
505
506
507 /*
508 *----------------------------------------------------------------------
509 *
510 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddUserCmd">AddUserCmd</a> --
511 *
512 * Implements the Tcl command ns_perm adduser
513 *
514 * Results:
515 * Tcl resut
516 *
517 * Side effects:
518 * A user may be added to the global user hash table
519 *
520 *----------------------------------------------------------------------
521 */
522
523 static int
524 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddUserCmd">AddUserCmd</a>(Server *servPtr, Tcl_Interp *interp, int argc, char **argv)
525 {
526 User *userPtr;
527 Group *groupPtr;
528 Tcl_HashSearch search;
529 Tcl_HashEntry *hPtr;
530 int new, i, allow;
531 char *name, *slash, *net;
532 struct in_addr ip, mask;
533
534 if (argc < 5 || argc == 6) {
535 Tcl_AppendResult(interp, "wrong # args: should be \"",
536 argv[0], " ", argv[1],
537 " name encpass userfield ?-allow|-deny host ...?\"",
538 NULL);
539 return TCL_ERROR;
540 }
541
542 allow = 0;
543 if (argc > 6) {
544 if (STREQ(argv[5], "-allow")) {
545 allow = 1;
546 } else if (!STREQ(argv[5], "-deny")) {
547 Tcl_AppendResult(interp, "invalid switch \"", argv[5], "\". ",
548 "Should be -allow or -deny",
549 NULL);
550 return TCL_ERROR;
551 }
552 }
553
554 name = argv[2];
555 userPtr = ns_malloc(sizeof(User));
556 strncpy(userPtr->pass, argv[3], sizeof(userPtr->pass) - 1);
557 Tcl_InitHashTable(&userPtr->nets, TCL_ONE_WORD_KEYS);
558 Tcl_InitHashTable(&userPtr->masks, TCL_ONE_WORD_KEYS);
559 Tcl_InitHashTable(&userPtr->hosts, TCL_STRING_KEYS);
560 Tcl_InitHashTable(&userPtr->groups, TCL_STRING_KEYS);
561 userPtr->filterallow = allow;
562
563 /*
564 * Loop over each parameter and figure out what it is. The
565 * possiblities are ipaddr/netmask, hostname, or partial hostname:
566 * 192.168.2.3/255.255.255.0, foo.bar.com, or .bar.com
567 */
568
569 for (i = 6; i < argc; ++i) {
570 mask.s_addr = INADDR_NONE;
571 net = argv[i];
572 slash = strchr(net, '/');
573 if (slash == NULL) {
574 hPtr = Tcl_CreateHashEntry(&userPtr->hosts, net, &new);
575 } else {
576
577 /*
578 * Try to conver the IP address/netmask into binary
579 * values.
580 */
581
582 *slash = '\0';
583 #ifndef _WIN32
584 if (inet_aton(net, &ip) == 0 || inet_aton(slash+1, &mask) == 0) {
585 #else
586 if (inet_pton(AF_INET,net, &ip) == 0 || inet_pton(AF_INET,slash+1, &mask) == 0) {
587 #endif
588 Tcl_AppendResult(interp, "invalid address or hostname \"",
589 net, "\". "
590 "should be ipaddr/netmask or hostname",
591 NULL);
592 goto fail;
593 }
594
595 /*
596 * Do a bitwise AND of the ip address with the netmask
597 * to make sure that all non-network bits are 0. That
598 * saves us from doing this operation every time a
599 * connection comes in.
600 */
601
602 ip.s_addr &= mask.s_addr;
603
604 /*
605 * Is this a new netmask? If so, add it to the list.
606 * A list of netmasks is maintained and every time a
607 * new connection comes in, the peer address is ANDed with
608 * each of them and a lookup on that address is done
609 * on the hash table of networks.
610 */
611
612 (void) Tcl_CreateHashEntry(&userPtr->masks,
613 (char *) mask.s_addr, &new);
614
615 hPtr = Tcl_CreateHashEntry(&userPtr->nets, (char *) ip.s_addr, &new);
616 Tcl_SetHashValue(hPtr, mask.s_addr);
617 }
618 if (!new) {
619 Tcl_AppendResult(interp, "duplicate entry: ", net, NULL);
620 goto fail;
621 }
622 }
623
624 /*
625 * Add the user.
626 */
627
628 hPtr = Tcl_CreateHashEntry(&servPtr->users, name, &new);
629 if (!new) {
630 Tcl_AppendResult(interp, "duplicate user: ", name, NULL);
631 goto fail;
632 }
633 Tcl_SetHashValue(hPtr, userPtr);
634 return TCL_OK;
635
636 fail:
637 hPtr = Tcl_FirstHashEntry(&userPtr->groups, &search);
638 while (hPtr != NULL) {
639 groupPtr = Tcl_GetHashValue(hPtr);
640 hPtr = Tcl_FindHashEntry(&groupPtr->users, name);
641 if (hPtr != NULL) {
642 Tcl_DeleteHashEntry(hPtr);
643 }
644 hPtr = Tcl_NextHashEntry(&search);
645 }
646 Tcl_DeleteHashTable(&userPtr->groups);
647 Tcl_DeleteHashTable(&userPtr->masks);
648 Tcl_DeleteHashTable(&userPtr->nets);
649 Tcl_DeleteHashTable(&userPtr->hosts);
650 ns_free(userPtr);
651 return TCL_ERROR;
652 }
653
654
655 /*
656 *----------------------------------------------------------------------
657 *
658 * <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddGroupCmd">AddGroupCmd</a> --
659 *
660 * Add a group to the global groups list
661 *
662 * Results:
663 * Standard tcl
664 *
665 * Side effects:
666 * A group will be created
667 *
668 *----------------------------------------------------------------------
669 */
670
671 static int
672 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AddGroupCmd">AddGroupCmd</a>(Server *servPtr, Tcl_Interp *interp, int argc, char *argv[])
673 {
674 char *name, *user;
675 User *userPtr;
676 Group *groupPtr;
677 Tcl_HashSearch search;
678 Tcl_HashEntry *hPtr;
679 int new, param;
680
681 if (argc < 4) {
682 Tcl_AppendResult(interp, "wrong # args: should be \"",
683 argv[0], " ", argv[1], " name user ?user ...?",
684 NULL);
685 return TCL_ERROR;
686 }
687
688 /*
689 * Create & populate the structure for a new group.
690 */
691
692 name = argv[2];
693 groupPtr = ns_malloc(sizeof(Group));
694 Tcl_InitHashTable(&groupPtr->users, TCL_STRING_KEYS);
695
696 /*
697 * Loop over each of the users who is to be in the group, make sure
698 * it's ok, and add him. Also put the group into the user's list
699 * of groups he's in.
700 */
701
702 for (param = 3; param < argc; param++) {
703 user = argv[param];
704 hPtr = Tcl_FindHashEntry(&servPtr->users, user);
705 if (hPtr == NULL) {
706 Tcl_AppendResult(interp, "no such user: ", user, NULL);
707 goto fail;
708 }
709 userPtr = Tcl_GetHashValue(hPtr);
710
711 /*
712 * Add the user to the group's list of users
713 */
714
715 hPtr = Tcl_CreateHashEntry(&groupPtr->users, user, &new);
716 if (!new) {
717 dupuser:
718 Tcl_AppendResult(interp,
719 "user \"", user, "\" already in group \"", name, "\"", NULL);
720 goto fail;
721 }
722 Tcl_SetHashValue(hPtr, userPtr);
723
724 /*
725 * Add the group to the user's list of groups
726 */
727
728 hPtr = Tcl_CreateHashEntry(&userPtr->groups, name, &new);
729 if (!new) {
730 goto dupuser;
731 }
732 Tcl_SetHashValue(hPtr, groupPtr);
733 }
734
735 /*
736 * Add the group to the global list of groups
737 */
738
739 hPtr = Tcl_CreateHashEntry(&servPtr->groups, name, &new);
740 if (!new) {
741 Tcl_AppendResult(interp, "duplicate group: ", name, NULL);
742 goto fail;
743 }
744 Tcl_SetHashValue(hPtr, groupPtr);
745 return TCL_OK;
746
747 fail:
748 hPtr = Tcl_FirstHashEntry(&groupPtr->users, &search);
749 while (hPtr != NULL) {
750 userPtr = Tcl_GetHashValue(hPtr);
751 hPtr = Tcl_FindHashEntry(&userPtr->groups, name);
752 if (hPtr != NULL) {
753 Tcl_DeleteHashEntry(hPtr);
754 }
755 hPtr = Tcl_NextHashEntry(&search);
756 }
757 Tcl_DeleteHashTable(&groupPtr->users);
758 ns_free(groupPtr);
759 return TCL_ERROR;
760 }
761
762
763 /*
764 *----------------------------------------------------------------------
765 *
766 * GroupCmd --
767 *
768 * Add a group to allow or deny access.
769 *
770 * Results:
771 * Std tcl
772 *
773 * Side effects:
774 * A perm record may be created, a group will be added to its
775 * deny list
776 *
777 *----------------------------------------------------------------------
778 */
779
780 static int
781 <a href="/cvs/aolserver/aolserver/nsperm/nsperm.c#A_AllowDenyCmd">AllowDenyCmd</a>(Server *servPtr, Tcl_Interp *interp, int argc, char **argv, int allow, int user)
782 {
783 Perm *permPtr;
784 Ns_DString base;
785 char *method, *url, *key;
786 int flags, new;
787
788 if (argc != 5 && argc != 6) {
789 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
790 " cmd ?-noinherit? method url key", NULL);
791 return TCL_ERROR;
792 }
793 if (argc != 6) {
794 flags = 0;
795 } else {
796 if (!STREQ(argv[2], "-noinherit")) {
797 Tcl_AppendResult(interp, "invalid option \"", argv[2],
798 "\": should be -noinherit", NULL);
799 return TCL_ERROR;
800 }
801 flags = NS_OP_NOINHERIT;
802 }
803 key = argv[argc-1];
804 url = argv[argc-2];
805 method = argv[argc-3];
806
807 /*
808 * Construct the base url.
809 */
810
811 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&base);
812 <a href="/cvs/aolserver/aolserver/nsd/pathname.c#A_Ns_NormalizePath">Ns_NormalizePath</a>(&base, url);
813
814 /*
815 * Locate and verify the exact record.
816 */
817
818 permPtr = <a href="/cvs/aolserver/aolserver/nsd/urlspace.c#A_Ns_UrlSpecificGet">Ns_UrlSpecificGet</a>(servPtr->server, method, url, uskey);
819 if (permPtr != NULL && !STREQ(base.string, permPtr->baseurl)) {
820 permPtr = NULL;
821 }
822 if (permPtr == NULL) {
823 permPtr = ns_malloc(sizeof(Perm));
824 permPtr->baseurl = <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringExport">Ns_DStringExport</a>(&base);
825 Tcl_InitHashTable(&permPtr->allowuser, TCL_STRING_KEYS);
826 Tcl_InitHashTable(&permPtr->denyuser, TCL_STRING_KEYS);
827 Tcl_InitHashTable(&permPtr->allowgroup, TCL_STRING_KEYS);
828 Tcl_InitHashTable(&permPtr->denygroup, TCL_STRING_KEYS);
829 <a href="/cvs/aolserver/aolserver/nsd/urlspace.c#A_Ns_UrlSpecificSet">Ns_UrlSpecificSet</a>(servPtr->server, method, url, uskey, permPtr, flags, NULL);
830 }
831 permPtr->implicit_allow = !allow;
832 if (user) {
833 if (allow) {
834 (void) Tcl_CreateHashEntry(&permPtr->allowuser, key, &new);
835 } else {
836 (void) Tcl_CreateHashEntry(&permPtr->denyuser, key, &new);
837 }
838 } else {
839 if (allow) {
840 (void) Tcl_CreateHashEntry(&permPtr->allowgroup, key, &new);
841 } else {
842 (void) Tcl_CreateHashEntry(&permPtr->denygroup, key, &new);
843 }
844 }
845 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&base);
846 return TCL_OK;
847 }