]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/snmp/agent/v2_0/src/mibgroup/mibII/vacm_vars.c
Initial revision
[karo-tx-redboot.git] / packages / net / snmp / agent / v2_0 / src / mibgroup / mibII / vacm_vars.c
1 // This file is part of eCos, the Embedded Configurable Operating System.
2 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
3 //
4 // eCos is free software; you can redistribute it and/or modify it under
5 // the terms of the GNU General Public License as published by the Free
6 // Software Foundation; either version 2 or (at your option) any later version.
7 //
8 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
9 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 // for more details.
12 //
13 // You should have received a copy of the GNU General Public License along
14 // with eCos; if not, write to the Free Software Foundation, Inc.,
15 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16 //
17 // As a special exception, if other files instantiate templates or use macros
18 // or inline functions from this file, or you compile this file and link it
19 // with other works to produce a work based on this file, this file does not
20 // by itself cause the resulting work to be covered by the GNU General Public
21 // License. However the source code for this file must still be made available
22 // in accordance with section (3) of the GNU General Public License.
23 //
24 // This exception does not invalidate any other reasons why a work based on
25 // this file might be covered by the GNU General Public License.
26 //
27 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
28 // at http://sources.redhat.com/ecos/ecos-license/
29 // -------------------------------------------
30 //####ECOSGPLCOPYRIGHTEND####
31 //####UCDSNMPCOPYRIGHTBEGIN####
32 //
33 // -------------------------------------------
34 //
35 // Portions of this software may have been derived from the UCD-SNMP
36 // project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
37 // California at Davis, which was originally based on the Carnegie Mellon
38 // University SNMP implementation.  Portions of this software are therefore
39 // covered by the appropriate copyright disclaimers included herein.
40 //
41 // The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
42 // -------------------------------------------
43 //
44 //####UCDSNMPCOPYRIGHTEND####
45 //==========================================================================
46 //#####DESCRIPTIONBEGIN####
47 //
48 // Author(s):    Manu Sharma
49 // Contributors: 
50 // Date:         2002-11-01
51 // Purpose:      Port of UCD-SNMP distribution to eCos.
52 // Description:  
53 //              
54 //
55 //####DESCRIPTIONEND####
56 //
57 //==========================================================================
58 /********************************************************************
59        Copyright 1989, 1991, 1992 by Carnegie Mellon University
60
61                           Derivative Work -
62 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
63
64                          All Rights Reserved
65
66 Permission to use, copy, modify and distribute this software and its
67 documentation for any purpose and without fee is hereby granted,
68 provided that the above copyright notice appears in all copies and
69 that both that copyright notice and this permission notice appear in
70 supporting documentation, and that the name of CMU and The Regents of
71 the University of California not be used in advertising or publicity
72 pertaining to distribution of the software without specific written
73 permission.
74
75 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
76 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
77 WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
78 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
79 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
80 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
81 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
82 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
83 *********************************************************************/
84 /*
85  * vacm_vars.c
86  *
87  * SNMPv3 View-based Access Control Model
88  */
89 /***********************************************************
90         Copyright 1988, 1989 by Carnegie Mellon University
91
92                       All Rights Reserved
93
94 Permission to use, copy, modify, and distribute this software and its 
95 documentation for any purpose and without fee is hereby granted, 
96 provided that the above copyright notice appear in all copies and that
97 both that copyright notice and this permission notice appear in 
98 supporting documentation, and that the name of CMU not be
99 used in advertising or publicity pertaining to distribution of the
100 software without specific, written prior permission.  
101
102 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
103 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
104 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
105 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
106 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
107 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
108 SOFTWARE.
109 ******************************************************************/
110
111 #include <config.h>
112
113 #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
114 #ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT
115
116 #if HAVE_STDLIB_H
117 #include <stdlib.h>
118 #endif
119 #if HAVE_UNISTD_H
120 #include <unistd.h>
121 #endif
122 #if HAVE_STRING_H
123 #include <string.h>
124 #else
125 #include <strings.h>
126 #endif
127 #if HAVE_MALLOC_H
128 #include <malloc.h>
129 #endif
130 #include <ctype.h>
131 #include <sys/types.h>
132 #if HAVE_NETINET_IN_H
133 #include <netinet/in.h>
134 #endif
135 #if HAVE_ARPA_INET_H
136 #include <arpa/inet.h>
137 #endif
138
139 #if HAVE_DMALLOC_H
140 #include <dmalloc.h>
141 #endif
142
143 #if HAVE_NETDB_H
144 #include <netdb.h>
145 #endif
146 #if HAVE_WINSOCK_H
147 #include <winsock.h>
148 #endif
149
150 #include "mibincl.h"
151 #include "read_config.h"
152 #include "agent_read_config.h"
153 #include "system.h"
154 #include "vacm.h"
155 #include "callback.h"
156 #include "agent_registry.h"
157 #include "agent_callbacks.h"
158 #include "vacm_vars.h"
159
160 #ifdef USING_MIBII_SYSORTABLE_MODULE
161 #if TIME_WITH_SYS_TIME
162 # ifdef WIN32
163 #  include <sys/timeb.h>
164 # else
165 #  include <sys/time.h>
166 # endif
167 # include <time.h>
168 #else
169 # if HAVE_SYS_TIME_H
170 #  include <sys/time.h>
171 # else
172 #  include <time.h>
173 # endif
174 #endif
175 #include <mibgroup/mibII/sysORTable.h>
176 #endif
177
178 void
179 init_vacm_vars (void) 
180 {
181
182 #ifdef USING_MIBII_SYSORTABLE_MODULE
183   static oid reg[] = {SNMP_OID_SNMPMODULES,16,2,2,1};
184 #endif
185   
186 #define PRIVRW  (SNMPV2ANY | 0x5000)
187
188   struct variable2 vacm_sec2group[] = {
189     {SECURITYGROUP, ASN_OCTET_STR, PRIVRW, var_vacm_sec2group, 1, {3}},
190     {SECURITYSTORAGE, ASN_INTEGER, PRIVRW, var_vacm_sec2group, 1, {4}},
191     {SECURITYSTATUS, ASN_INTEGER, PRIVRW, var_vacm_sec2group, 1, {5}},
192   };
193
194   struct variable2 vacm_access[] = {
195     {ACCESSMATCH, ASN_INTEGER, PRIVRW, var_vacm_access, 1, {4}},
196     {ACCESSREAD, ASN_OCTET_STR, PRIVRW, var_vacm_access, 1, {5}},
197     {ACCESSWRITE, ASN_OCTET_STR, PRIVRW, var_vacm_access, 1, {6}},
198     {ACCESSNOTIFY, ASN_OCTET_STR, PRIVRW, var_vacm_access, 1, {7}},
199     {ACCESSSTORAGE, ASN_INTEGER, PRIVRW, var_vacm_access, 1, {8}},
200     {ACCESSSTATUS, ASN_INTEGER, PRIVRW, var_vacm_access, 1, {9}},
201   };
202
203   struct variable2 vacm_view[] = {
204     {VIEWMASK, ASN_OCTET_STR, PRIVRW, var_vacm_view, 1, {3}},
205     {VIEWTYPE, ASN_INTEGER, PRIVRW, var_vacm_view, 1, {4}},
206     {VIEWSTORAGE, ASN_INTEGER, PRIVRW, var_vacm_view, 1, {5}},
207     {VIEWSTATUS, ASN_INTEGER, PRIVRW, var_vacm_view, 1, {6}},
208   };
209
210 /* Define the OID pointer to the top of the mib tree that we're
211    registering underneath */
212   oid vacm_sec2group_oid[] = { OID_VACMGROUPENTRY };
213   oid vacm_access_oid[] = { OID_VACMACCESSENTRY};
214   oid vacm_view_oid[] = { OID_VACMVIEWENTRY };
215
216   /* register ourselves with the agent to handle our mib tree */
217   REGISTER_MIB("mibII/vacm:sec2group", vacm_sec2group, variable2, \
218                vacm_sec2group_oid);
219   REGISTER_MIB("mibII/vacm:access", vacm_access, variable2, vacm_access_oid);
220   REGISTER_MIB("mibII/vacm:view", vacm_view, variable2, vacm_view_oid);
221
222   snmpd_register_config_handler("com2sec", vacm_parse_security,
223                                 vacm_free_security,"name source community");
224   snmpd_register_config_handler("group", vacm_parse_group, vacm_free_group,
225                                 "name v1|v2c|usm security");
226   snmpd_register_config_handler("access", vacm_parse_access, vacm_free_access,
227                             "name context model level prefx read write notify");
228   snmpd_register_config_handler("view", vacm_parse_view, vacm_free_view,
229                                 "name type subtree [mask]");
230   snmpd_register_config_handler("rwcommunity", vacm_parse_simple,
231                                 NULL,"community [default|hostname|network/bits] [oid]");
232   snmpd_register_config_handler("rocommunity", vacm_parse_simple,
233                                 NULL,"community [default|hostname|network/bits] [oid]");
234   snmpd_register_config_handler("rwuser", vacm_parse_simple,
235                                 NULL,"user [noauth|auth|priv] [oid]");
236   snmpd_register_config_handler("rouser", vacm_parse_simple,
237                                 NULL,"user [noauth|auth|priv] [oid]");
238
239 #ifdef USING_MIBII_SYSORTABLE_MODULE
240   register_sysORTable(reg,10,"View-based Access Control Model for SNMP.");
241 #endif
242
243   /* register ourselves to handle access control */
244   snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK,
245                          vacm_in_view_callback, NULL);
246   snmp_register_callback(SNMP_CALLBACK_APPLICATION,
247                          SNMPD_CALLBACK_ACM_CHECK_INITIAL,
248                          vacm_in_view_callback, NULL);
249 }
250
251 static struct vacm_securityEntry *securityFirst =0, *securityLast =0;
252
253 #define EXAMPLE_NETWORK         "NETWORK"
254 #define EXAMPLE_COMMUNITY       "COMMUNITY"
255
256 void vacm_parse_security (const char *token, 
257                           char *param)
258 {
259     char *name, *source, *community;
260     const char *mask;
261     char *cp;
262     struct vacm_securityEntry *sp, se;
263     int maskLength, maskBit;
264     struct sockaddr_in *srcIp, *srcMask;
265     char null[] = "";
266
267     memset (&se, 0 , sizeof se);
268     name = strtok(param, "\t\n ");
269     if (!name) {
270         config_perror("missing NAME parameter");
271         return;
272     }
273     source = strtok(NULL, "\t\n ");
274     if (!source) {
275         config_perror("missing SOURCE parameter");
276         return;
277     }
278     if ( !strncmp( source, EXAMPLE_NETWORK, strlen(EXAMPLE_NETWORK)) ) {
279         config_perror("Example config NETWORK not properly configured");
280         return;         /* or exit(1); */
281     }
282     community = strtok(NULL, "\t\n ");
283     if (!community) {
284         config_perror("missing COMMUNITY parameter");
285         return;
286     }
287     if ( !strncmp( community, EXAMPLE_COMMUNITY, strlen(EXAMPLE_COMMUNITY)) ) {
288         config_perror("Example config COMMUNITY not properly configured");
289         return;         /* or exit(1); */
290     }
291     srcIp   = (struct sockaddr_in*)&(se.sourceIp);
292     srcMask = (struct sockaddr_in*)&(se.sourceMask);
293     cp = strchr(source, '/');
294     if (cp == NULL) cp = null;
295     else *cp++ = 0;
296     mask = cp;
297     if (strcmp("default", source) == 0 || strcmp("0.0.0.0", source) == 0) {
298         memset(&(srcIp->sin_addr), 0, sizeof(struct in_addr));
299         mask = "0.0.0.0";
300     }
301     else if ((srcIp->sin_addr.s_addr = inet_addr (source)) == (unsigned) -1) {
302         struct hostent *hp = gethostbyname(source);
303         if (hp != NULL) {
304             memcpy(&(srcIp->sin_addr), hp->h_addr, 4);
305         }
306         else {
307             config_perror ("bad source address");
308             return;
309         }
310     }
311     if (*mask == 0) memset (&(srcMask->sin_addr), 0xff, sizeof(struct in_addr));
312     else {
313         if (strchr(mask, '.')) {
314             if ((srcMask->sin_addr.s_addr = inet_addr(mask)) == (unsigned)-1) {
315                 config_perror("bad mask");
316                 return;
317             }
318         }
319         else {
320             maskLength = atoi(mask);
321             if (maskLength <= 0 || maskLength > 32) {
322                 config_perror("bad mask length");
323                 return;
324             }
325             maskBit = 0x80000000L;
326             srcMask->sin_addr.s_addr = 0;
327             while (maskLength--) {
328                 srcMask->sin_addr.s_addr |= maskBit;
329                 maskBit >>= 1;
330             }
331             srcMask->sin_addr.s_addr = htonl(srcMask->sin_addr.s_addr);
332         }
333     }
334     if ((srcIp->sin_addr.s_addr & ~srcMask->sin_addr.s_addr) != 0) {
335         config_perror("source/mask mismatch");
336         return;
337     }
338     if (strlen(name)+1 > sizeof(se.securityName)) {
339         config_perror("security name too long");
340         return;
341     }
342     if (strlen(community)+1 > sizeof(se.community)) {
343         config_perror("community name too long");
344         return;
345     }
346     strcpy(se.securityName, name);
347     strcpy(se.community, community);
348     sp = (struct vacm_securityEntry *)malloc (sizeof *sp);
349     if (sp == NULL) {
350         config_perror("memory error");
351         return;
352     }
353     *sp = se;
354     if (securityFirst != NULL) {
355         securityLast->next = sp;
356         securityLast = sp;
357     }
358     else {
359         securityFirst = securityLast = sp;
360     }
361 }
362
363 void vacm_free_security (void)
364 {
365     struct vacm_securityEntry *sp;
366     while ((sp = securityFirst)) {
367         securityFirst = sp->next;
368         free(sp);
369     }
370 }
371
372 void vacm_parse_group (const char *token, 
373                        char *param)
374 {
375     char *group, *model, *security;
376     int imodel;
377     struct vacm_groupEntry *gp = NULL;
378
379     group = strtok (param, " \t\n");
380     model = strtok (NULL, " \t\n");
381     security = strtok (NULL, " \t\n");
382
383     if (group == NULL || *group == 0) {
384         config_perror("missing GROUP parameter");
385         return;
386     }
387     if (model == NULL || *model == 0) {
388         config_perror("missing MODEL parameter");
389         return;
390     }
391     if (security == NULL || *security == 0) {
392         config_perror("missing SECURITY parameter");
393         return;
394     }
395     if (strcasecmp(model, "v1") == 0) imodel = SNMP_SEC_MODEL_SNMPv1;
396     else if (strcasecmp(model, "v2c") == 0) imodel = SNMP_SEC_MODEL_SNMPv2c;
397     else if (strcasecmp(model, "usm") == 0) imodel = SNMP_SEC_MODEL_USM;
398     else if (strcasecmp(model, "any") == 0) {
399         config_perror("bad security model \"any\" should be: v1, v2c or usm - installing anyway");
400         imodel = SNMP_SEC_MODEL_ANY;
401     }
402     else {
403         config_perror("bad security model, should be: v1, v2c or usm");
404         return;
405     }
406     if (strlen(security)+1 > sizeof(gp->groupName)) {
407         config_perror("security name too long");
408         return;
409     }
410     gp = vacm_createGroupEntry(imodel, security);
411     if (!gp) {
412         config_perror("failed to create group entry");
413         return;
414     }
415     strcpy (gp->groupName, group);
416     gp->storageType = SNMP_STORAGE_PERMANENT;
417     gp->status = SNMP_ROW_ACTIVE;
418     free (gp->reserved);
419     gp->reserved = NULL;
420 }
421
422 void vacm_free_group (void)
423 {
424     vacm_destroyAllGroupEntries();
425 }
426
427 void vacm_parse_access (const char *token, char *param)
428 {
429     char *name, *context, *model, *level, *prefix, *readView, *writeView, *notify;
430     int imodel, ilevel, iprefix;
431     struct vacm_accessEntry *ap;
432
433     name = strtok(param, " \t\n");
434     if (!name) {
435         config_perror("missing NAME parameter");
436         return;
437     }
438     context = strtok(NULL, " \t\n");
439     if (!context) {
440         config_perror("missing CONTEXT parameter");
441         return;
442     }
443     model = strtok(NULL, " \t\n");
444     if (!model) {
445         config_perror("missing MODEL parameter");
446         return;
447     }
448     level = strtok(NULL, " \t\n");
449     if (!level) {
450         config_perror("missing LEVEL parameter");
451         return;
452     }
453     prefix = strtok(NULL, " \t\n");
454     if (!prefix) {
455         config_perror("missing PREFIX parameter");
456         return;
457     }
458     readView = strtok(NULL, " \t\n");
459     if (!readView) {
460         config_perror("missing readView parameter");
461         return;
462     }
463     writeView = strtok(NULL, " \t\n");
464     if (!writeView) {
465         config_perror("missing writeView parameter");
466         return;
467     }
468     notify = strtok(NULL, " \t\n");
469     if (!notify) {
470         config_perror("missing notifyView parameter");
471         return;
472     }
473     if (strcmp(context, "\"\"") == 0) *context = 0;
474     if (strcasecmp(model, "any") == 0) imodel = SNMP_SEC_MODEL_ANY;
475     else if (strcasecmp(model, "v1") == 0) imodel = SNMP_SEC_MODEL_SNMPv1;
476     else if (strcasecmp(model, "v2c") == 0) imodel = SNMP_SEC_MODEL_SNMPv2c;
477     else if (strcasecmp(model, "usm") == 0) imodel = SNMP_SEC_MODEL_USM;
478     else {
479         config_perror("bad security model (any, v1, v2c, usm)");
480         return;
481     }
482     if (strcasecmp(level, "noauth") == 0) ilevel = SNMP_SEC_LEVEL_NOAUTH;
483     else if (strcasecmp(level, "noauthnopriv") == 0) ilevel = SNMP_SEC_LEVEL_NOAUTH;
484     else if (strcasecmp(level, "auth") == 0) ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
485     else if (strcasecmp(level, "authnopriv") == 0) ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
486     else if (strcasecmp(level, "priv") == 0) ilevel = SNMP_SEC_LEVEL_AUTHPRIV;
487     else if (strcasecmp(level, "authpriv") == 0) ilevel = SNMP_SEC_LEVEL_AUTHPRIV;
488     else {
489         config_perror("bad security level (noauthnopriv, authnopriv, authpriv)");
490         return;
491     }
492     if (strcmp(prefix,"exact") == 0) iprefix = 1;
493     else if (strcmp(prefix,"prefix") == 0) iprefix = 2;
494     else if (strcmp(prefix,"0") == 0) {
495         config_perror("bad prefix match parameter \"0\", should be: exact or prefix - installing anyway");
496         iprefix = 1;
497     }
498     else {
499         config_perror("bad prefix match parameter, should be: exact or prefix");
500         return;
501     }
502     if (strlen(readView)+1 > sizeof(ap->readView)) {
503         config_perror("readView too long");
504         return;
505     }
506     if (strlen(writeView)+1 > sizeof(ap->writeView)) {
507         config_perror("writeView too long");
508         return;
509     }
510     if (strlen(notify)+1 > sizeof(ap->notifyView)) {
511         config_perror("notifyView too long");
512         return;
513     }
514     ap = vacm_createAccessEntry (name, context, imodel, ilevel);
515     if (!ap) {
516         config_perror("failed to create access entry");
517         return;
518     }
519     strcpy(ap->readView, readView);
520     strcpy(ap->writeView, writeView);
521     strcpy(ap->notifyView, notify);
522     ap->contextMatch = iprefix;
523     ap->storageType = SNMP_STORAGE_PERMANENT;
524     ap->status = SNMP_ROW_ACTIVE;
525     free (ap->reserved);
526     ap->reserved = NULL;
527 }
528
529 void vacm_free_access (void)
530 {
531     vacm_destroyAllAccessEntries();
532 }
533
534 void vacm_parse_view (const char *token, 
535                       char *param)
536 {
537     char *name, *type, *subtree, *mask;
538     int inclexcl;
539     struct vacm_viewEntry *vp;
540     oid suboid[MAX_OID_LEN];
541     size_t suboid_len = 0;
542     u_char viewMask[sizeof (vp->viewMask)];
543     int i;
544
545     name = strtok (param, " \t\n");
546     if (!name) {
547         config_perror("missing NAME parameter");
548         return;
549     }
550     type = strtok (NULL, " \n\t");
551     if (!type) {
552         config_perror("missing TYPE parameter");
553         return;
554     }
555     subtree = strtok(NULL, " \t\n");
556     if (!subtree) {
557         config_perror("missing SUBTREE parameter");
558         return;
559     }
560     mask = strtok(NULL, " \t\n");
561
562     if (strcmp(type, "included") == 0) inclexcl = SNMP_VIEW_INCLUDED;
563     else if (strcmp(type, "excluded") == 0) inclexcl = SNMP_VIEW_EXCLUDED;
564     else {
565         config_perror("TYPE must be included/excluded?");
566         return;
567     }
568     suboid_len = MAX_OID_LEN;
569     if (!read_objid(subtree, suboid, &suboid_len)) {
570         config_perror("bad SUBTREE object id");
571         return;
572     }
573     if (mask) {
574         int val;
575         i = 0;
576         for (mask = strtok(mask, ".:"); mask; mask = strtok(NULL, ".:")) {
577             if (i >= sizeof(viewMask)) {
578                 config_perror("MASK too long");
579                 return;
580             }
581             if (sscanf(mask, "%x", &val) == 0) {
582                 config_perror("invalid MASK");
583                 return;
584             }
585             viewMask[i] = val;
586             i++;
587         }
588     }
589     else {
590         for (i = 0; i < sizeof(viewMask); i++)
591             viewMask[i] = 0xff;
592     }
593     vp = vacm_createViewEntry(name, suboid, suboid_len);
594     if (!vp) {
595         config_perror("failed to create view entry");
596         return;
597     }
598     memcpy(vp->viewMask, viewMask, sizeof(viewMask));
599     vp->viewType = inclexcl;
600     vp->viewStorageType = SNMP_STORAGE_PERMANENT;
601     vp->viewStatus = SNMP_ROW_ACTIVE;
602     free (vp->reserved);
603     vp->reserved = NULL;
604 }
605
606 void vacm_free_view (void)
607 {
608     vacm_destroyAllViewEntries();
609 }
610
611 void vacm_parse_simple(const char *token, char *confline) {
612   char line[SPRINT_MAX_LEN];
613   char community[COMMUNITY_MAX_LEN];
614   char theoid[SPRINT_MAX_LEN];
615   char viewname[SPRINT_MAX_LEN];
616   char addressname[SPRINT_MAX_LEN];
617   const char *rw = "none";
618   const char *model = "any";
619   char *cp;
620   static int num = 0;
621   char secname[SPRINT_MAX_LEN];
622   char authtype[SPRINT_MAX_LEN];
623
624   /* community name or user name */
625   cp = copy_word(confline, community);
626
627   if (strcmp(token,"rouser") == 0 || strcmp(token,"rwuser") == 0) {
628     /* authentication type */
629     if (cp && *cp)
630       cp = copy_word(cp, authtype);
631     else
632       strcpy(authtype, "auth");
633     DEBUGMSGTL((token, "setting auth type: \"%s\"\n",authtype));
634     model = "usm";
635   } else {
636     /* source address */
637     if (cp && *cp) {
638       cp = copy_word(cp, addressname);
639     } else {
640       strcpy(addressname, "default");
641     }
642     /* authtype has to be noauth */
643     strcpy(authtype, "noauth");
644   }
645
646   /* oid they can touch */
647   if (cp && *cp) {
648     cp = copy_word(cp, theoid);
649   } else {
650     strcpy(theoid, ".1");
651   }
652
653   if (strcmp(token,"rwcommunity") == 0 || strcmp(token,"rwuser") == 0)
654     rw = viewname;
655
656   if (strcmp(token,"rwcommunity") == 0 || strcmp(token,"rocommunity") == 0) {
657     /* com2sec mapping */
658     /* com2sec anonymousSecNameNUM    ADDRESS  COMMUNITY */
659     sprintf(secname, "anonymousSecName%03d", num);
660     sprintf(line,"%s %s %s", secname, addressname, community);
661     DEBUGMSGTL((token,"passing: %s %s\n", "com2sec", line));
662     vacm_parse_security("com2sec",line);
663
664     /* sec->group mapping */
665     /* group   anonymousGroupNameNUM  any      anonymousSecNameNUM */
666     sprintf(line,"anonymousGroupName%03d v1 %s", num, secname);
667     DEBUGMSGTL((token,"passing: %s %s\n", "group", line));
668     vacm_parse_group("group",line);
669     sprintf(line,"anonymousGroupName%03d v2c %s", num, secname);
670     DEBUGMSGTL((token,"passing: %s %s\n", "group", line));
671     vacm_parse_group("group",line);
672   } else {
673     strcpy(secname, community);
674
675     /* sec->group mapping */
676     /* group   anonymousGroupNameNUM  any      anonymousSecNameNUM */
677     sprintf(line,"anonymousGroupName%03d usm %s", num, secname);
678     DEBUGMSGTL((token,"passing: %s %s\n", "group", line));
679     vacm_parse_group("group",line);
680   }
681
682
683   /* view definition */
684   /* view    anonymousViewNUM       included OID */
685   sprintf(viewname,"anonymousView%03d",num);
686   sprintf(line,"%s included %s", viewname, theoid);
687   DEBUGMSGTL((token,"passing: %s %s\n", "view", line));
688   vacm_parse_view("view",line);
689
690   /* map everything together */
691   /* access  anonymousGroupNameNUM  "" MODEL AUTHTYPE exact anonymousViewNUM [none/anonymousViewNUM] [none/anonymousViewNUM] */
692   sprintf(line, "anonymousGroupName%03d  \"\" %s %s exact %s %s %s", num,
693           model, authtype, viewname, rw, rw);
694   DEBUGMSGTL((token,"passing: %s %s\n", "access", line));
695   vacm_parse_access("access",line);
696   num++;
697 }
698
699 int
700 vacm_in_view_callback(int majorID, int minorID, void *serverarg,
701                       void *clientarg) {
702   struct view_parameters *view_parms = (struct view_parameters *) serverarg;
703   int retval;
704   
705   if (view_parms == NULL)
706     return 1;
707   retval = vacm_in_view(view_parms->pdu, view_parms->name,
708                         view_parms->namelen);
709   if (retval != 0)
710     view_parms->errorcode = retval;
711   return retval;
712 }
713
714
715 /*******************************************************************-o-******
716  * vacm_in_view
717  *
718  * Parameters:
719  *      *pdu
720  *      *name
721  *       namelen
722  *      
723  * Returns:
724  *      0       On success.
725  *      1       Missing security name.
726  *      2       Missing group
727  *      3       Missing access
728  *      4       Missing view
729  *      5       Not in view
730  *
731  * Debug output listed as follows:
732  *      <securityName> <groupName> <viewName> <viewType>
733  */
734 int vacm_in_view (struct snmp_pdu *pdu,
735                   oid *name,
736                   size_t namelen)
737 {
738     struct vacm_securityEntry *sp = securityFirst;
739     struct vacm_accessEntry *ap;
740     struct vacm_groupEntry *gp;
741     struct vacm_viewEntry *vp;
742     struct sockaddr_in *pduIp = (struct sockaddr_in*)&(pdu->address);
743     struct sockaddr_in *srcIp, *srcMask;
744     char *vn;
745     char *sn;
746
747     if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c) {
748         if (snmp_get_do_debugging()) {
749             char *buf;
750             if (pdu->community) {
751                 buf = malloc(1+ pdu->community_len);
752                 memcpy(buf, pdu->community, pdu->community_len);
753                 buf[pdu->community_len] = '\0';
754             } else {
755                 DEBUGMSGTL(("mibII/vacm_vars", "NULL community"));
756                 buf = strdup("NULL");
757             }
758             
759             DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: ver=%d, source=%.8x, community=%s\n", pdu->version, pduIp->sin_addr.s_addr, buf));
760             free (buf);
761         }
762
763         /* allow running without snmpd.conf */
764         if (sp == NULL && !vacm_is_configured()) {
765             DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: accepted with no com2sec entries\n"));
766             switch (pdu->command) {
767             case SNMP_MSG_GET:
768             case SNMP_MSG_GETNEXT:
769             case SNMP_MSG_GETBULK:
770                 return 0;
771             default:
772                 return 1;
773             }
774         }
775         while (sp) {
776             srcIp   = (struct sockaddr_in *)&(sp->sourceIp);
777             srcMask = (struct sockaddr_in *)&(sp->sourceMask);
778             if ((pduIp->sin_addr.s_addr & srcMask->sin_addr.s_addr)
779                     == srcIp->sin_addr.s_addr
780                 && strlen(sp->community) == pdu->community_len
781                 && !strncmp(sp->community, (char *)pdu->community, pdu->community_len))
782                 break;
783             sp = sp->next;
784         }
785         if (sp == NULL) return 1;
786         sn = sp->securityName;
787     } else if (pdu->securityModel == SNMP_SEC_MODEL_USM) {
788       DEBUGMSG (("mibII/vacm_vars",
789                  "vacm_in_view: ver=%d, model=%d, secName=%s\n",
790                  pdu->version, pdu->securityModel, pdu->securityName));
791       sn = pdu->securityName;
792     } else {
793         sn = NULL;
794     }
795
796     if (sn == NULL) return 1;
797     DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: sn=%s", sn));
798
799     gp = vacm_getGroupEntry(pdu->securityModel, sn);
800     if (gp == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return 2; }
801     DEBUGMSG (("mibII/vacm_vars", ", gn=%s", gp->groupName));
802
803     ap = vacm_getAccessEntry(gp->groupName, "", pdu->securityModel,
804                              pdu->securityLevel);
805     if (ap == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return 3; }
806
807     if (name == 0) { /* only check the setup of the vacm for the request */
808         DEBUGMSG(("mibII/vacm_vars", ", Done checking setup\n"));
809         return 0;
810     }
811
812     switch (pdu->command) {
813       case SNMP_MSG_GET:
814       case SNMP_MSG_GETNEXT:
815       case SNMP_MSG_GETBULK:
816         vn = ap->readView;
817         break;
818       case SNMP_MSG_SET:
819         vn = ap->writeView;
820         break;
821       case SNMP_MSG_TRAP:
822       case SNMP_MSG_TRAP2:
823       case SNMP_MSG_INFORM:
824         vn = ap->notifyView;
825         break;
826       default:
827         snmp_log(LOG_ERR, "bad msg type in vacm_in_view: %d\n", pdu->command);
828         vn = ap->readView;
829     }
830     DEBUGMSG (("mibII/vacm_vars", ", vn=%s", vn));
831
832     vp = vacm_getViewEntry (vn, name, namelen);
833     if (vp == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return 4; }
834     DEBUGMSG(("mibII/vacm_vars", ", vt=%d\n", vp->viewType));
835     if (vp->viewType == SNMP_VIEW_EXCLUDED) return 5;
836
837     return 0;
838
839 }  /* end vacm_in_view() */
840
841
842 u_char *var_vacm_sec2group(struct variable *vp,
843                            oid *name,
844                            size_t *length,
845                            int exact,
846                            size_t *var_len,
847                            WriteMethod **write_method)
848 {
849     struct vacm_groupEntry *gp;
850     oid *groupSubtree;
851     int groupSubtreeLen;
852     int secmodel;
853     char secname[32], *cp;
854
855     write_method = NULL;
856     if (memcmp(name, vp->name, sizeof(oid)*vp->namelen) != 0) {
857         memcpy(name, vp->name, sizeof(oid)*vp->namelen);
858         *length = vp->namelen;
859     }
860     if (exact) {
861         if (*length < 13) return NULL;
862
863         secmodel = name[11];
864         groupSubtree = name+13;
865         groupSubtreeLen = *length - 13;
866         cp = secname;
867         while (groupSubtreeLen-- > 0) {
868             if (*groupSubtree > 255)
869               return 0; /* illegal value */
870             *cp++ = (char) *groupSubtree++;
871         }
872         *cp = 0;
873
874         gp = vacm_getGroupEntry(secmodel, secname);
875     }
876     else {
877         secmodel = *length > 11 ? name[11] : 0;
878         groupSubtree = name+12;
879         groupSubtreeLen = *length - 12;
880         cp = secname;
881         while (groupSubtreeLen-- > 0) {
882             if (*groupSubtree > 255)
883               return 0; /* illegal value */
884             *cp++ = (char) *groupSubtree++;
885         }
886         *cp = 0;
887         vacm_scanGroupInit();
888         while ((gp = vacm_scanGroupNext()) != NULL) {
889             if (gp->securityModel > secmodel ||
890                 (gp->securityModel == secmodel && strcmp(gp->securityName, secname) > 0))
891                 break;
892         }
893         if (gp) {
894             name[11] = gp->securityModel;
895             *length = 12;
896             cp = gp->securityName;
897             while (*cp) {
898                 name[(*length)++] = *cp++;
899             }
900         }
901     }
902
903     if (!gp) return NULL;
904
905     *var_len =sizeof(long_return);
906     switch (vp->magic) {
907     case SECURITYMODEL:
908         long_return = gp->securityModel;
909         return (u_char *)&long_return;
910     case SECURITYNAME:
911         *var_len = gp->securityName[0];
912         return (u_char *)&gp->securityName[1];
913     case SECURITYGROUP:
914         *var_len = strlen(gp->groupName);
915         return (u_char *)gp->groupName;
916     case SECURITYSTORAGE:
917         long_return = gp->storageType;
918         return (u_char *)&long_return;
919     case SECURITYSTATUS:
920         long_return = gp->status;
921         return (u_char *)&long_return;
922     }
923     return NULL;
924 }
925
926 u_char *var_vacm_access(struct variable *vp,
927                         oid *name,
928                         size_t *length,
929                         int exact,
930                         size_t *var_len,
931                         WriteMethod **write_method)
932 {
933     struct vacm_accessEntry *gp;
934     int secmodel;
935     int seclevel;
936     char groupName[32];
937     char contextPrefix[32];
938     oid *op;
939     int len;
940     char *cp;
941     int cmp;
942
943     write_method = NULL;
944     if (memcmp(name, vp->name, sizeof(oid)*vp->namelen) != 0) {
945         memcpy(name, vp->name, sizeof(oid)*vp->namelen);
946         *length = vp->namelen;
947     }
948     if (exact) {
949         if (*length < 15) return NULL;
950
951         op = name+11;
952         len = *op++;
953         cp = groupName;
954         while (len-- > 0) {
955             if (*op > 255)
956               return 0; /* illegal value */
957             *cp++ = (char) *op++;
958         }
959         *cp = 0;
960         len = *op++;
961         cp = contextPrefix;
962         while (len-- > 0) {
963             if (*op > 255)
964               return 0; /* illegal value */
965             *cp++ = (char) *op++;
966         }
967         *cp = 0;
968         secmodel = *op++;
969         seclevel = *op++;
970         if (op != name + *length) {
971             return NULL;
972         }
973
974         gp = vacm_getAccessEntry(groupName, contextPrefix, secmodel, seclevel);
975     }
976     else {
977         secmodel = seclevel = 0;
978         groupName[0] = 0;
979         contextPrefix[0] = 0;
980         op = name+11;
981         if (op >= name + *length) {
982         }
983         else {
984             len = *op;
985             cp = groupName;
986             while (len-- >= 0) {
987                 if (*op > 255)
988                   return 0; /* illegal value */
989                 *cp++ = (char) *op++;
990             }
991             *cp = 0;
992         }
993         if (op >= name + *length) {
994         }
995         else {
996             len = *op;
997             cp = contextPrefix;
998             while (len-- >= 0) {
999                 if (*op > 255)
1000                   return 0; /* illegal value */
1001                 *cp++ = (char) *op++;
1002             }
1003             *cp = 0;
1004         }
1005         if (op >= name + *length) {
1006         }
1007         else {
1008             secmodel = *op++;
1009         }
1010         if (op >= name + *length) {
1011         }
1012         else {
1013             seclevel = *op++;
1014         }
1015         vacm_scanAccessInit();
1016         while ((gp = vacm_scanAccessNext()) != NULL) {
1017             cmp = strcmp(gp->groupName, groupName);
1018             if (cmp > 0) break;
1019             if (cmp < 0) continue;
1020             cmp = strcmp(gp->contextPrefix, contextPrefix);
1021             if (cmp > 0) break;
1022             if (cmp < 0) continue;
1023             if (gp->securityModel > secmodel) break;
1024             if (gp->securityModel < secmodel) continue;
1025             if (gp->securityLevel > seclevel) break;
1026         }
1027         if (gp) {
1028             *length = 11;
1029             cp = gp->groupName;
1030             do {
1031                 name[(*length)++] = *cp++;
1032             } while (*cp);
1033             cp = gp->contextPrefix;
1034             do {
1035                 name[(*length)++] = *cp++;
1036             } while (*cp);
1037             name[(*length)++] = gp->securityModel;
1038             name[(*length)++] = gp->securityLevel;
1039         }
1040     }
1041
1042     if (!gp) return NULL;
1043
1044     *var_len =sizeof(long_return);
1045     switch (vp->magic) {
1046     case ACCESSMATCH:
1047         long_return = gp->contextMatch;
1048         return (u_char *)&long_return;
1049     case ACCESSLEVEL:
1050         long_return = gp->securityLevel;
1051         return (u_char *)&long_return;
1052     case ACCESSMODEL:
1053         long_return = gp->securityModel;
1054         return (u_char *)&long_return;
1055     case ACCESSPREFIX:
1056         *var_len = *gp->contextPrefix;
1057         return (u_char *)&gp->contextPrefix[1];
1058     case ACCESSREAD:
1059         *var_len = strlen(gp->readView);
1060         return (u_char *)gp->readView;
1061     case ACCESSWRITE:
1062         *var_len = strlen(gp->writeView);
1063         return (u_char *)gp->writeView;
1064     case ACCESSNOTIFY:
1065         *var_len = strlen(gp->notifyView);
1066         return (u_char *)gp->notifyView;
1067     case ACCESSSTORAGE:
1068         long_return = gp->storageType;
1069         return (u_char *)&long_return;
1070     case ACCESSSTATUS:
1071         long_return = gp->status;
1072         return (u_char *)&long_return;
1073     }
1074     return NULL;
1075 }
1076
1077 u_char *var_vacm_view(struct variable *vp,
1078                       oid *name,
1079                       size_t *length,
1080                       int exact,
1081                       size_t *var_len,
1082                       WriteMethod **write_method)
1083 {
1084     struct vacm_viewEntry *gp;
1085     char viewName[32];
1086     oid subtree[MAX_OID_LEN];
1087     size_t subtreeLen = 0;
1088     oid *op, *op1;
1089     int len;
1090     char *cp;
1091     int cmp;
1092
1093     write_method = NULL;
1094     if (memcmp(name, vp->name, sizeof(oid)*vp->namelen) != 0) {
1095         memcpy(name, vp->name, sizeof(oid)*vp->namelen);
1096         *length = vp->namelen;
1097     }
1098     if (exact) {
1099         if (*length < 15) return NULL;
1100
1101         op = name+12;
1102         len = *op++;
1103         cp = viewName;
1104         while (len-- > 0) {
1105             if (*op > 255)
1106               return 0; /* illegal value */
1107             *cp++ = (char) *op++;
1108         }
1109         *cp = 0;
1110         len = *length - (op - name);
1111         op1 = subtree;
1112         while (len-- > 0) {
1113             *op1++ = *op++;
1114             subtreeLen++;
1115         }
1116         if (op != name + *length) {
1117             return NULL;
1118         }
1119
1120         gp = vacm_getViewEntry(viewName, subtree, subtreeLen);
1121     }
1122     else {
1123         viewName[0] = 0;
1124         op = name+12;
1125         if (op >= name + *length) {
1126         }
1127         else {
1128             len = *op;
1129             cp = viewName;
1130             while (len-- >= 0) {
1131                 if (*op > 255)
1132                   return 0; /* illegal value */
1133                 *cp++ = (char) *op++;
1134             }
1135             *cp = 0;
1136         }
1137         if (op >= name + *length) {
1138         }
1139         else {
1140             len = *length - (op - name);
1141             op1 = subtree;
1142             while (len-- >= 0) {
1143                 *op1++ = *op++;
1144                 subtreeLen++;
1145             }
1146         }
1147         vacm_scanViewInit();
1148         while ((gp = vacm_scanViewNext()) != NULL) {
1149             cmp = strcmp(gp->viewName, viewName);
1150             if (cmp > 0) break;
1151             if (cmp < 0) continue;
1152         }
1153         if (gp) {
1154             *length = 12;
1155             cp = gp->viewName;
1156             do {
1157                 name[(*length)++] = *cp++;
1158             } while (*cp);
1159             op1 = gp->viewSubtree;
1160             len = gp->viewSubtreeLen;
1161             do {
1162                 name[(*length)++] = *op1++;
1163             } while (len-- > 0);
1164         }
1165     }
1166
1167     if (!gp) return NULL;
1168
1169     *var_len =sizeof(long_return);
1170     switch (vp->magic) {
1171     case VIEWNAME:
1172         *var_len = gp->viewName[0];
1173         return (u_char *)&gp->viewName[1];
1174     case VIEWSUBTREE:
1175         *var_len = gp->viewSubtreeLen*sizeof(oid);
1176         return (u_char *)gp->viewSubtree;
1177     case VIEWMASK:
1178         *var_len = (gp->viewSubtreeLen + 7) / 8;
1179         return (u_char *)gp->viewMask;
1180     case VIEWTYPE:
1181         long_return = gp->viewType;
1182         return (u_char *)&long_return;
1183     case VIEWSTORAGE:
1184         long_return = gp->viewStorageType;
1185         return (u_char *)&long_return;
1186     case VIEWSTATUS:
1187         long_return = gp->viewStatus;
1188         return (u_char *)&long_return;
1189     }
1190     return NULL;
1191 }
1192
1193 #endif /* CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT */
1194 #endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */