#######################################################################
#
+# 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
{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}},
{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}},
oid *name,
size_t name_len)
{
- int ret, i;
+ long i;
int big = SNMP_MAX_LEN;
switch (action)
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;
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;
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;
{ "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 }
};
/* SMUX password. */
extern char *smux_password;
+/* SNMP write access allowed */
+extern int snmp_write_access;
+
/* SMUX socket */
extern int smuxfd;
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,
u_char *statP = NULL;
WriteMethod *write_method = NULL;
+ if (!snmp_write_access)
+ return SNMP_ERR_NOSUCHNAME;
+
/* Check */
for (l = treelist; l; l=l->next)
{
/* 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
/* There is no instance. */
if (*val == NULL)
- return SNMP_NOSUCHINSTANCE;
+ return SNMP_ERR_NOSUCHNAME;
/* Call is suceed. */
*val_type = v->type;
/* 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
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;
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);
memcpy (reqid, save, savelen * sizeof(oid));
*reqid_len = savelen;
- return SNMP_NOSUCHOBJECT;
+ return SNMP_ERR_NOSUCHNAME;
}
/* GET message header. */
&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));
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);
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