SMUX patches from Jochen Friedrich <jochen+freeradius-devel@scram.de>
authoraland <aland>
Tue, 3 Oct 2000 14:36:36 +0000 (14:36 +0000)
committeraland <aland>
Tue, 3 Oct 2000 14:36:36 +0000 (14:36 +0000)
raddb/radiusd.conf.in
src/main/radius_snmp.c
src/main/radiusd.c
src/main/smux.c

index ba5bd4d..aa17eb4 100644 (file)
@@ -181,6 +181,44 @@ proxy_requests     = yes
 
 #######################################################################
 #
+#  SNMP configuration
+#
+#  NOTE: This part is only working if your radiusd is compiled with SNMP
+#  support.
+#
+#  smux_password: Password used for SMUX registration.
+#
+#  Specifies password used when connecting to the SNMP master agent.
+#  This must match the password as configured on the agent. The OID
+#  used to register the radius subagent is 1.3.6.1.4.1.3317.1.3.1.
+#  A sample entry for the ucd-snmp deamon looks like this:
+#
+#  smuxpeer .1.3.6.1.4.1.3317.1.3.1 verysecret
+#
+#  A sample entry for AIX 4.3 is:
+#
+#  smux 1.3.6.1.4.1.3317.1.3.1 verysecret
+#
+#  The default password is an empty password.
+#
+#smux_password = verysecret
+#
+#  snmp_write_access:
+#
+#  Controls if write access to the radiusd via SNMP is enabled or not.
+#  Set this value to yes, if you want to be able to reload radiusd from
+#  your network management station.
+#
+#  For this to work, you also have to make sure that your master agent
+#  is configured to allow SNMP set requests. For security reasons, this
+#  setting defaults to no.
+#
+# allowed values: {no, yes}
+#
+#snmp_write_access = yes
+
+#######################################################################
+#
 #  Proxy server configuration
 #
 #  This entry controls the servers behaviour towards ALL other servers
index 157688f..83bbd0b 100644 (file)
@@ -124,7 +124,7 @@ static struct variable radiusacc_variables[] =
   {RADIUSACCSERVTOTALPACKETSDROPPED, COUNTER, RONLY, radAccServ, 1, {11}},
   {RADIUSACCSERVTOTALNORECORDS, COUNTER, RONLY, radAccServ, 1, {12}},
   {RADIUSACCSERVTOTALUNKNOWNTYPES, COUNTER, RONLY, radAccServ, 1, {13}},
-  {RADIUSACCCLIENTADDRESS, STRING, RONLY, radAccEntry, 3, {14,1,2}},
+  {RADIUSACCCLIENTADDRESS, IPADDRESS, RONLY, radAccEntry, 3, {14,1,2}},
   {RADIUSACCCLIENTID, STRING, RONLY, radAccEntry, 3, {14,1,3}},
   {RADIUSACCSERVPACKETSDROPPED, COUNTER, RONLY, radAccEntry, 3, {14,1,4}},
   {RADIUSACCSERVREQUESTS, COUNTER, RONLY, radAccEntry, 3, {14,1,5}},
@@ -153,7 +153,7 @@ static struct variable radiusauth_variables[] =
   {RADIUSAUTHSERVTOTALBADAUTHENTICATORS, COUNTER, RONLY, radAuthServ, 1, {12}},
   {RADIUSAUTHSERVTOTALPACKETSDROPPED, COUNTER, RONLY, radAuthServ, 1, {13}},
   {RADIUSAUTHSERVTOTALUNKNOWNTYPES, COUNTER, RONLY, radAuthServ, 1, {14}},
-  {RADIUSAUTHCLIENTADDRESS, STRING, RONLY, radAuthEntry, 3, {15,1,2}},
+  {RADIUSAUTHCLIENTADDRESS, IPADDRESS, RONLY, radAuthEntry, 3, {15,1,2}},
   {RADIUSAUTHCLIENTID, STRING, RONLY, radAuthEntry, 3, {15,1,3}},
   {RADIUSAUTHSERVACCESSREQUESTS, COUNTER, RONLY, radAuthEntry, 3, {15,1,4}},
   {RADIUSAUTHSERVDUPACCESSREQUESTS, COUNTER, RONLY, radAuthEntry, 3, {15,1,5}},
@@ -229,7 +229,7 @@ radServReset (int action,
     oid      *name,
     size_t   name_len)
 {
-    int ret, i;
+    long i;
     int big = SNMP_MAX_LEN;
 
     switch (action)
@@ -340,12 +340,16 @@ radAccEntry(struct variable *vp,
     switch (vp->magic) {
 
     case RADIUSACCCLIENTADDRESS:
-        *var_len = strlen(c->longname);
-        return c->longname;
+        *var_len = sizeof(c->ipaddr);
+        return (unsigned char *)&(c->ipaddr);
 
     case RADIUSACCCLIENTID:
-        *var_len = strlen(c->shortname);
-        return c->shortname;
+       if (strlen(c->shortname)) {
+               *var_len = strlen(c->shortname);
+               return c->shortname;
+       }
+        *var_len = strlen(c->longname);
+        return c->longname;
 
     case RADIUSACCSERVPACKETSDROPPED:
         return (unsigned char *) NULL;
@@ -465,12 +469,16 @@ radAuthEntry(struct variable *vp,
     switch (vp->magic) {
 
     case RADIUSAUTHCLIENTADDRESS:
-        *var_len = strlen(c->longname);
-        return (unsigned char *) c->longname;
+        *var_len = sizeof(c->ipaddr);
+        return (unsigned char *)&(c->ipaddr);
 
     case RADIUSAUTHCLIENTID:
-        *var_len = strlen(c->shortname);
-        return (unsigned char *) c->shortname;
+       if (strlen(c->shortname)) {
+               *var_len = strlen(c->shortname);
+               return c->shortname;
+       }
+        *var_len = strlen(c->longname);
+        return c->longname;
 
     case RADIUSAUTHSERVACCESSREQUESTS:
         return (unsigned char *) NULL;
index 518178b..8077e5f 100644 (file)
@@ -73,6 +73,7 @@ char                  *radlog_dir = NULL;
 const char             *radlib_dir = NULL;
 #ifdef WITH_SNMP
 char                   *smux_password = NULL;
+int                    snmp_write_access = FALSE;
 int                    snmp_acctotalrequests = 0;
 int                    snmp_authtotalrequests = 0;
 enum smux_event         smux_event = SMUX_NONE;
@@ -180,6 +181,7 @@ static CONF_PARSER server_config[] = {
   { "hostname_lookups",   PW_TYPE_BOOLEAN,    &librad_dodns,      "0" },
 #ifdef WITH_SNMP
   { "smux_password",      PW_TYPE_STRING_PTR, &smux_password,     "" },
+  { "snmp_write_access",  PW_TYPE_BOOLEAN,    &snmp_write_access, "no" },
 #endif
   { NULL, -1, NULL, NULL }
 };
index d379e0e..116dd7f 100644 (file)
@@ -51,6 +51,9 @@ size_t smux_oid_len;
 /* SMUX password. */
 extern char *smux_password;
 
+/* SNMP write access allowed */
+extern int snmp_write_access;
+
 /* SMUX socket */
 extern int smuxfd;
 
@@ -383,8 +386,9 @@ smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
   return ptr;
 }
 
-/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on ucd-snmp
-   smux and as such suppose, that the peer recieves in the message only one variable */
+/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on
+   ucd-snmp smux and as such suppose, that the peer receives in the message
+   only one variable. Fortunately, IBM seems to do the same in AIX. */
 
 int
 smux_set (oid *reqid, size_t *reqid_len,
@@ -401,6 +405,9 @@ smux_set (oid *reqid, size_t *reqid_len,
   u_char *statP = NULL;
   WriteMethod *write_method = NULL;
 
+  if (!snmp_write_access)
+    return SNMP_ERR_NOSUCHNAME;
+
   /* Check */
   for (l = treelist; l; l=l->next)
     {
@@ -447,11 +454,11 @@ smux_set (oid *reqid, size_t *reqid_len,
               /* If above execution is failed or oid is small (so
                  there is no further match). */
               if (result < 0)
-                return SNMP_NOSUCHOBJECT;
+                return SNMP_ERR_NOSUCHNAME;
             }
         }
     }
-  return SNMP_NOSUCHOBJECT;
+  return SNMP_ERR_NOSUCHNAME;
 }
 
 int
@@ -502,7 +509,7 @@ smux_get (oid *reqid, size_t *reqid_len, int exact,
 
                  /* There is no instance. */
                  if (*val == NULL)
-                   return SNMP_NOSUCHINSTANCE;
+                   return SNMP_ERR_NOSUCHNAME;
 
                  /* Call is suceed. */
                  *val_type = v->type;
@@ -513,11 +520,11 @@ smux_get (oid *reqid, size_t *reqid_len, int exact,
              /* If above execution is failed or oid is small (so
                  there is no further match). */
              if (result < 0)
-               return SNMP_NOSUCHOBJECT;
+               return SNMP_ERR_NOSUCHNAME;
            }
        }
     }
-  return SNMP_NOSUCHOBJECT;
+  return SNMP_ERR_NOSUCHNAME;
 }
 
 int
@@ -540,7 +547,8 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
   oid_copy (save, reqid, *reqid_len);
   savelen = *reqid_len;
 
-  /* Check */
+  /* Check for best matching subtree */
+
   for (l = treelist; l; l=l->next)
     {
       subtree = l->data;
@@ -548,22 +556,34 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
       subresult = oid_compare_part (reqid, *reqid_len, 
                                    subtree->name, subtree->name_len);
 
-      /* If request is in the tree. The agent has to make sure we
-         only receive requests we have registered for. */
-      if (subresult == 0)
+     /* If request is in the tree. The agent has to make sure we
+        only receive requests we have registered for. */
+     /* Unfortunately, that's not true. In fact, a SMUX subagent has to
+        behave as if it manages the whole SNMP MIB tree itself. It's the
+        duty of the master agent to collect the best answer and return it
+        to the manager. See RFC 1227 chapter 3.1.6 for the glory details
+        :-). ucd-snmp really behaves bad here as it actually might ask
+        multiple times for the same GETNEXT request as it throws away the
+        answer when it expects it in a different subtree and might come
+        back later with the very same request. --jochen */
+
+      if (subresult <= 0)
        {
-
          /* Prepare suffix. */
          suffix = reqid + subtree->name_len;
          suffix_len = *reqid_len - subtree->name_len;
-         result = subresult;
-
+         if (subresult < 0)
+           {
+             oid_copy(reqid, subtree->name, subtree->name_len);
+             *reqid_len = subtree->name_len;
+           }
          for (j = 0; j < subtree->variables_num; j++)
            {
+             result = subresult;
              v = &subtree->variables[j];
 
              /* Next then check result >= 0. */
-             if (result >= 0)
+             if (result == 0)
                result = oid_compare_part (suffix, suffix_len,
                                           v->name, v->namelen);
 
@@ -590,7 +610,7 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
   memcpy (reqid, save, savelen * sizeof(oid));
   *reqid_len = savelen;
 
-  return SNMP_NOSUCHOBJECT;
+  return SNMP_ERR_NOSUCHNAME;
 }
 
 /* GET message header. */
@@ -947,7 +967,7 @@ smux_register ()
                          &priority, sizeof (u_long));
 
       /* Operation. */
-      operation = 1;
+      operation = snmp_write_access ? 2 : 1; /* Register R/O or R/W */
       ptr = asn_build_int (ptr, &len, 
                          (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
                          &operation, sizeof (u_long));
@@ -1114,8 +1134,8 @@ void
 smux_register_mib(char *descr, struct variable *var, size_t width, int num, 
                  oid name[], size_t namelen)
 {
-  struct subtree *tree;
-  struct list *l;
+  struct subtree *tree, *tt;
+  struct list *l, *ll;
 
   tree = (struct subtree *)malloc(sizeof(struct subtree));
   oid_copy (tree->name, name, namelen);
@@ -1127,14 +1147,30 @@ smux_register_mib(char *descr, struct variable *var, size_t width, int num,
   l = (struct list *)malloc(sizeof(struct list));
   l->data = tree;
   l->next = NULL;
+/* Build a treelist sorted by the name. This makes GETNEXT simpler */
   if (treelist == NULL)
-    treelist = l;
-  else
     {
-      struct list *ll;
-      for (ll = treelist; ll->next; ll=ll->next);
-      ll->next = l;
+      treelist = l;
+      return;
+    }
+  tt = (struct subtree*) treelist->data;
+  if (oid_compare(name, namelen, tt->name, tt->name_len) < 0)
+    {
+      l->next = treelist;
+      treelist = l;
+      return;
+    }
+  for (ll = treelist; ll->next; ll=ll->next)
+    {
+      tt = (struct subtree*) ll->next->data;
+      if (oid_compare(name, namelen, tt->name, tt->name_len) < 0)
+       {
+         l->next = ll->next;
+         ll->next = l;
+         return;
+       }
     }
+  ll->next = l;
 }
 
 void