/** Builds an accounting request for port id client_port with the value_pairs at send * * @note NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled in by this function, the rest has to be supplied. * * @param rh a handle to parsed configuration. * @param client_port the client port number to use (may be zero to use any available). * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME). * @return received value_pairs in @received, and %OK_RC (0) on success, negative on failure as return value. */ int rc_acct(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send) { return rc_aaa(rh, client_port, send, NULL, NULL, 1, PW_ACCOUNTING_REQUEST); }
/** Builds an accounting request with the value_pairs at send * * @param rh a handle to parsed configuration. * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME). * @return %OK_RC (0) on success, negative on failure as return value. */ int rc_acct_proxy(rc_handle *rh, VALUE_PAIR *send) { return rc_aaa(rh, 0, send, NULL, NULL, 0, PW_ACCOUNTING_REQUEST); }
/** Builds an authentication request for proxying * * Builds an authentication request with the value_pairs send and submits it to a server. * Works for a proxy; does not add IP address, and does does not rely on config file. * * @param rh a handle to parsed configuration. * @param client_port the client port number to use (may be zero to use any available). * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME). * @param received an allocated array of received values. * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of * any %PW_REPLY_MESSAGE received. * @return received value_pairs in @received, messages from the server in msg (if non-NULL) * and %OK_RC (0) on success, negative on failure as return value. */ int rc_auth_proxy(rc_handle *rh, VALUE_PAIR *send, VALUE_PAIR **received, char *msg) { return rc_aaa(rh, 0, send, received, msg, 0, PW_ACCESS_REQUEST); }
/** Builds an authentication request for port id client_port with the value_pairs send and submits it to a server * * @param rh a handle to parsed configuration. * @param client_port the client port number to use (may be zero to use any available). * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME). * @param received an allocated array of received values. * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of any * %PW_REPLY_MESSAGE received. * @return received value_pairs in @received, messages from the server in msg (if non-NULL), * and %OK_RC (0) on success, negative on failure as return value. */ int rc_auth(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg) { return rc_aaa(rh, client_port, send, received, msg, 1, PW_ACCESS_REQUEST); }
int rc_acct_proxy(rc_handle *rh, VALUE_PAIR *send) { char msg[4096]; return rc_aaa(rh, 0, send, NULL, msg, 0, PW_ACCOUNTING_REQUEST); }
/* 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; } } }
int rc_acct(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send) { char msg[4096]; return rc_aaa(rh, 0, client_port, send, NULL, msg, 1, PW_ACCOUNTING_REQUEST); }