From aa008d0769a8e2c1f529b92585659336c0f11953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 19 Aug 2010 22:53:12 +0300 Subject: auth: experimental (untested) support for port reauthentication Ability to force reauthentication (HP ProCurve specific) for the switch port to which we traced the IP. This works currently only with the HP WebAuth scheme (should be possible with MAC auth scheme too). --- squark-auth.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/squark-auth.c b/squark-auth.c index d0b3390..4b88913 100644 --- a/squark-auth.c +++ b/squark-auth.c @@ -83,6 +83,8 @@ static const oid LLDP_lldpRemManAddrIfSubtype[] = { 1, 0, 8802, 1, 1, 2, 1, 4, 2, 1, 3 }; static const oid HP_hpicfUsrAuthWebAuthSessionName[] = { SNMP_OID_ENTERPRISES, 11, 2, 14, 11, 5, 1, 19, 5, 1, 1, 2 }; +static const oid HP_hpicfUsrAuthPortReauthenticate[] = + { SNMP_OID_ENTERPRISES, 11, 2, 14, 11, 5, 1, 19, 2, 1, 1, 4 }; static const oid SEMI_MIB_hpHttpMgVersion[] = { SNMP_OID_ENTERPRISES, 11, 2, 36, 1, 1, 2, 6, 0 }; @@ -90,7 +92,9 @@ static const oid SEMI_MIB_hpHttpMgVersion[] = struct switch_info; -static int num_queries = 0, running = TRUE; +static int num_queries = 0; +static int running = TRUE; +static int kick_out = FALSE; static const char *snmp_community = NULL; static const char *username_format = "%w"; @@ -553,28 +557,28 @@ static void blob_push_formatted_username( blob_push(b, BLOB_PTR_LEN(o, p - o)); switch (p[1]) { case 'I': - blob_push(b, BLOB_STR(addr_print(&auth->addr))); + blob_push(b, BLOB_STRLEN((char*) addr_print(&auth->addr))); break; case 'M': blob_push_hexdump(b, BLOB_BUF(auth->mac)); break; case 'N': - blob_push(b, BLOB_STR(si->system_name)); + blob_push(b, BLOB_STRLEN(si->system_name)); break; case 'L': - blob_push(b, BLOB_STR(si->system_location)); + blob_push(b, BLOB_STRLEN(si->system_location)); break; case 'i': blob_push_uint(b, auth->local_port, 10); break; case 'n': - blob_push(b, BLOB_STR(auth->port_name)); + blob_push(b, BLOB_STRLEN(auth->port_name)); break; case 'd': - blob_push(b, BLOB_STR(auth->port_descr)); + blob_push(b, BLOB_STRLEN(auth->port_descr)); break; case 'w': - blob_push(b, BLOB_STR(auth->webauth_name)); + blob_push(b, BLOB_STRLEN(auth->webauth_name)); break; default: o = p; @@ -584,7 +588,7 @@ static void blob_push_formatted_username( p += 2; o = p; } - blob_push(b, BLOB_STR(o)); + blob_push(b, BLOB_STRLEN((char*) o)); } static int auth_ok(struct auth_context *auth) @@ -597,7 +601,7 @@ static void auth_completed(struct auth_context *auth) char tmp[256]; blob_t b = BLOB_BUF(tmp); - blob_push(&b, BLOB_STR(auth->token)); + blob_push(&b, BLOB_STRLEN(auth->token)); if (auth_ok(auth)) { blob_push(&b, BLOB_STR(" OK user=")); blob_push_formatted_username(&b, username_format, auth); @@ -641,6 +645,27 @@ static blob_t var_parse_type(netsnmp_variable_list **varptr, int asn_tag) return BLOB_PTR_LEN(var->val.string, var->val_len); } +static void auth_force_reauthentication(struct auth_context *auth) +{ + struct switch_info *si = auth->current_switch; + netsnmp_pdu *pdu; + oid query_oids[ARRAY_SIZE(HP_hpicfUsrAuthPortReauthenticate)+1]; + blob_t b = BLOB_BUF(query_oids); + long one = 1; + + pdu = snmp_pdu_create(SNMP_MSG_SET); + blob_push(&b, BLOB_OID(HP_hpicfUsrAuthPortReauthenticate)); + blob_push_oid(&b, auth->local_port); + b = blob_pushed(BLOB_OID(query_oids), b); + + snmp_pdu_add_variable(pdu, oid_blob(b), ASN_INTEGER, + (u_char *) &one, sizeof(one)); + + /* Send asynchornously - ignore response */ + if (snmp_send(si->session, pdu) == 0) + snmp_free_pdu(pdu); +} + static int auth_handle_portinfo_reply(int oper, netsnmp_session *s, int reqid, netsnmp_pdu *resp, void *data) { struct auth_context *auth = data; @@ -664,6 +689,9 @@ static int auth_handle_portinfo_reply(int oper, netsnmp_session *s, int reqid, n auth->info_available |= FORMAT_PORT_WEBAUTH; done: + if (kick_out && auth_ok(auth)) + auth_force_reauthentication(auth); + auth_completed(auth); return 1; } @@ -1040,12 +1068,12 @@ int main(int argc, char **argv) struct timeval timeout; sockaddr_any addr; fd_set fdset; - int opt, fds, block; + int opt, fds, block, i; setenv("MIBS", "", 1); init_snmp("squark-auth"); - while ((opt = getopt(argc, argv, "c:r:i:R:v:f:T:")) != -1) { + while ((opt = getopt(argc, argv, "c:r:i:R:v:f:T:K")) != -1) { switch (opt) { case 'c': snmp_community = optarg; @@ -1068,8 +1096,13 @@ int main(int argc, char **argv) case 'T': load_topology(optarg); break; + case 'K': + kick_out = TRUE; + break; } } + argc -= optind; + argv += optind; if (l3_root == NULL || l3_ifname == NULL || l2_vlan == NULL) { printf("Mandatory information missing\n"); @@ -1080,11 +1113,19 @@ int main(int argc, char **argv) l2_root = l3_root; l3_root_dev = get_switch(addr_parse(l3_root, &addr)); - l3_if_ndx = resolve_ifName2ifIndex(l3_root_dev, BLOB_STR((char *) l3_ifname)); + l3_if_ndx = resolve_ifName2ifIndex(l3_root_dev, BLOB_STRLEN((char *) l3_ifname)); l2_root_dev = get_switch(addr_parse(l2_root, &addr)); l2_vlan_ndx = atoi(l2_vlan); username_format_flags = parse_format(username_format); + if (kick_out) + username_format_flags |= FORMAT_PORT_WEBAUTH; + + for (i = 0; i < argc; i++) { + start_authentication(argv[i], argv[i]); + running = FALSE; + } + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); while (num_queries || running) { fds = 0; -- cgit v1.2.3