static void append_routes(DBusMessageIter *iter, void *user_data) { GHashTable *routes = user_data; GHashTableIter hash; gpointer value, key; if (routes == NULL) { append_route(iter, NULL); return; } g_hash_table_iter_init(&hash, routes); while (g_hash_table_iter_next(&hash, &key, &value) == TRUE) { DBusMessageIter dict; dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &dict); append_route(&dict, value); dbus_message_iter_close_container(iter, &dict); } }
static void append_routes(DBusMessageIter *iter, void *user_data) { GSList *list, *routes = user_data; DBG("routes %p", routes); for (list = routes; list != NULL; list = g_slist_next(list)) { DBusMessageIter dict; struct vpn_route *route = list->data; dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &dict); append_route(&dict, route); dbus_message_iter_close_container(iter, &dict); } }
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name. */ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len) { struct radius_ctx_st *pctx = ctx; VALUE_PAIR *send = NULL, *recvd = NULL; uint32_t service; char route[64]; char txt[64]; int ret; /* send Access-Request */ syslog(LOG_DEBUG, "radius-auth: communicating username (%s) and password", pctx->username); if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); return ERR_AUTH_FAIL; } if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, (char*)pass, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } if (pctx->our_ip[0] != 0) { struct in_addr in; struct in6_addr in6; if (inet_pton(AF_INET, pctx->our_ip, &in) != 0) { in.s_addr = ntohl(in.s_addr); rc_avpair_add(rh, &send, PW_NAS_IP_ADDRESS, (char*)&in, sizeof(struct in_addr), 0); } else if (inet_pton(AF_INET6, pctx->our_ip, &in6) != 0) { rc_avpair_add(rh, &send, PW_NAS_IPV6_ADDRESS, (char*)&in6, sizeof(struct in6_addr), 0); } } if (nas_identifier[0] != 0) { if (rc_avpair_add(rh, &send, PW_NAS_IDENTIFIER, nas_identifier, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } } if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, pctx->remote_ip, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } if (pctx->user_agent[0] != 0) { if (rc_avpair_add(rh, &send, PW_CONNECT_INFO, pctx->user_agent, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } } service = PW_AUTHENTICATE_ONLY; if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } service = PW_ASYNC; if (rc_avpair_add(rh, &send, PW_NAS_PORT_TYPE, &service, -1, 0) == NULL) { syslog(LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__, pctx->username); ret = ERR_AUTH_FAIL; goto cleanup; } ret = rc_aaa(rh, pctx->id, send, &recvd, NULL, 1, PW_ACCESS_REQUEST); if (ret == OK_RC) { VALUE_PAIR *vp = recvd; uint32_t ipv4; uint8_t ipv6[16]; while(vp != NULL) { if (vp->attribute == PW_SERVICE_TYPE && vp->lvalue != PW_FRAMED) { syslog(LOG_ERR, "%s:%u: unknown radius service type '%d'", __func__, __LINE__, (int)vp->lvalue); goto fail; } else if (vp->attribute == RAD_GROUP_NAME && vp->type == PW_TYPE_STRING) { /* Group-Name */ parse_groupnames(pctx, vp->strvalue); } else if (vp->attribute == PW_FRAMED_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) { /* Framed-IPv6-Address */ if (inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) { pctx->ipv6_subnet_prefix = 64; strlcpy(pctx->ipv6_net, pctx->ipv6, sizeof(pctx->ipv6_net)); } } else if (vp->attribute == PW_DELEGATED_IPV6_PREFIX && vp->type == PW_TYPE_IPV6PREFIX) { /* Delegated-IPv6-Prefix */ if (inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) { memset(ipv6, 0, sizeof(ipv6)); memcpy(ipv6, vp->strvalue+2, vp->lvalue-2); if (inet_ntop(AF_INET6, ipv6, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) { pctx->ipv6_subnet_prefix = (unsigned)(unsigned char)vp->strvalue[1]; } } } else if (vp->attribute == PW_FRAMED_IPV6_PREFIX && vp->type == PW_TYPE_IPV6PREFIX) { if (vp->lvalue > 2 && vp->lvalue <= 18) { /* Framed-IPv6-Prefix */ memset(ipv6, 0, sizeof(ipv6)); memcpy(ipv6, vp->strvalue+2, vp->lvalue-2); if (inet_ntop(AF_INET6, ipv6, txt, sizeof(txt)) != NULL) { snprintf(route, sizeof(route), "%s/%u", txt, (unsigned)(unsigned char)vp->strvalue[1]); append_route(pctx, vp->strvalue, vp->lvalue); } } } else if (vp->attribute == PW_DNS_SERVER_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) { /* DNS-Server-IPv6-Address */ if (pctx->ipv6_dns1[0] == 0) inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns1, sizeof(pctx->ipv6_dns1)); else inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns2, sizeof(pctx->ipv6_dns2)); } else if (vp->attribute == PW_FRAMED_IP_ADDRESS && vp->type == PW_TYPE_IPADDR) { /* Framed-IP-Address */ ipv4 = htonl(vp->lvalue); inet_ntop(AF_INET, &ipv4, pctx->ipv4, sizeof(pctx->ipv4)); } else if (vp->attribute == PW_FRAMED_IP_NETMASK && vp->type == PW_TYPE_IPADDR) { /* Framed-IP-Netmask */ ipv4 = htonl(vp->lvalue); inet_ntop(AF_INET, &ipv4, pctx->ipv4_mask, sizeof(pctx->ipv4_mask)); } else if (vp->attribute == RAD_IPV4_DNS1 && vp->type == PW_TYPE_IPADDR) { /* MS-Primary-DNS-Server */ ipv4 = htonl(vp->lvalue); inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns1, sizeof(pctx->ipv4_dns1)); } else if (vp->attribute == RAD_IPV4_DNS2 && vp->type == PW_TYPE_IPADDR) { /* MS-Secondary-DNS-Server */ ipv4 = htonl(vp->lvalue); inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns2, sizeof(pctx->ipv4_dns2)); } else if (vp->attribute == PW_FRAMED_ROUTE && vp->type == PW_TYPE_STRING) { /* Framed-Route */ append_route(pctx, vp->strvalue, vp->lvalue); } else if (vp->attribute == PW_FRAMED_IPV6_ROUTE && vp->type == PW_TYPE_STRING) { /* Framed-IPv6-Route */ append_route(pctx, vp->strvalue, vp->lvalue); } else if (vp->attribute == PW_ACCT_INTERIM_INTERVAL && vp->type == PW_TYPE_INTEGER) { pctx->interim_interval_secs = vp->lvalue; } else if (vp->attribute == PW_SESSION_TIMEOUT && vp->type == PW_TYPE_INTEGER) { pctx->session_timeout_secs = vp->lvalue; } else { syslog(LOG_DEBUG, "radius-auth: ignoring server's value %u of type %u", (int)vp->attribute, (int)vp->type); } vp = vp->next; } ret = 0; cleanup: rc_avpair_free(send); if (recvd != NULL) rc_avpair_free(recvd); return ret; } else { fail: if (send != NULL) rc_avpair_free(send); if (recvd != NULL) rc_avpair_free(recvd); if (ret == PW_ACCESS_CHALLENGE) { pctx->pass_msg = pass_msg_second; return ERR_AUTH_CONTINUE; } else if (pctx->retries++ < MAX_PASSWORD_TRIES-1) { pctx->pass_msg = pass_msg_failed; return ERR_AUTH_CONTINUE; } else { syslog(LOG_AUTH, "radius-auth: error authenticating user '%s'", pctx->username); return ERR_AUTH_FAIL; } } }