📄 radiusd.c
字号:
int msg_id; char *buf;#endif salen = sizeof (rad_saremote); sin = (struct sockaddr_in *) & rad_saremote; result = recvfrom (fd, (char *) recv_buffer, (int) sizeof(recv_buffer), (int) 0, (struct sockaddr *)&rad_saremote, &salen); addr = ntohl(sin->sin_addr.s_addr); port = ntohs(sin->sin_port); if (result < AUTH_HDR_LEN) { log_err("rad_request: runt packet of %d bytes from %s.%d\n", result,ipaddr2strp(addr),port); return; } /* * Validate the requesting IP address - * Not secure, but worth the check for accidental requests * find_client() logs an error message if needed */ if(find_client(addr, secret, sizeof(secret), hostnm, sizeof(hostnm)) != 0) { log_err("rad_request: request from unknown" " client %s.%d ignored\n",ipaddr2strp(addr),port); return; } authreq = radrecv( addr, port, secret, recv_buffer, result ); if (authreq == (AUTH_REQ *)NULL) { /* malformed packet */ return; } /* handle_proxy places the user name in authreq->name, * and forwards request to a proxy server if necessary */ if (handle_proxy(authreq) != 0) { /* error or forwarded */ if (authreq->flags & REQ_FREE) { reqfree(authreq,"rad_request"); } /* otherwise authreq will be freed when proxy response is seen */ return; }#if defined(SMARTCARD) if (spawn_flag == 0) { radrespond(authreq, fd); return; } /* * We need to see if this is a challenge response */ child_pid = -1; if ((pair = get_attribute(authreq->request,PW_STATE)) != (VALUE_PAIR *)NULL) { buf = pair->strvalue; debug("rad_request: PW_STATE<%s>\n", buf);#ifdef SECURID /* * the format for SECURID state string is * * SECURID_xxxx=n * * xxxx is commands: next or npin or wait * n is the child pid */ if (strncmp(buf, "SECURID_", 8) == 0) { child_pid = (int)atoi(&buf[13]); }#endif /* SECURID */#ifdef ACTIVCARD /* * the format for ACTIVCARD state string is * * ACTIVCARD_999...=n * * 999... is the challenge returned by ActivEngine * n is the child pid */ if (strncmp(buf, "ACTIVCARD_", 10) == 0) { child_pid = (int)atoi(strchr(buf, (int)'=')+1); }#endif /* ACTIVCARD */ } if (child_pid == -1) { radrespond(authreq, fd); return; } debug("rad_request: challenge_response from %s for child %d\n", req2strp(authreq), child_pid); curreq = first_request; while(curreq != (AUTH_REQ *)NULL) { if (curreq->child_pid == child_pid) { break; } curreq = curreq->next; } if (curreq == (AUTH_REQ *)NULL) { log_err("rad_request: child %d not found\n", child_pid); reqfree(authreq,"rad_request"); return; } if (curreq->ipaddr != addr) { log_err("rad_request: error: mismatched IP addresses in request %x != %x for ID %d %d\n", curreq->ipaddr, addr, curreq->id, auth->id); reqfree(authreq,"rad_request"); return; } if (curreq->udp_port != port) { log_err("rad_request: error: mismatched source ports in request %d != %d for ID %d %d\n", curreq->udp_port, port, curreq->id, auth->id); reqfree(authreq,"rad_request"); return; } if (curreq->id == authreq->id) { /* This is a duplicate request - just drop it */ log_err("rad_request: dropped duplicate ID %d\n", authreq->id); reqfree(authreq,"rad_request"); return; } msg_key = RADIUS_MSG_KEY(child_pid); if ((msg_id = msgget(msg_key, 0600)) == -1) { log_err("rad_request: error: msgget for key %x for id %d returned error %d\n",msg_key, msg_id, errno); reqfree(authreq,"rad_request"); return; } if (msgsnd(msg_id, recv_buffer, result, IPC_NOWAIT) == -1) { log_err("rad_request: error: msgsnd for key %x for id %d returned error %d\n", msg_key, msg_id, errno); reqfree(authreq,"rad_request"); return; } curreq->id = authreq->id;#else /* not SMARTCARD */ radrespond(authreq, fd);#endif /* not SMARTCARD */}/************************************************************************* * * Function: radrecv * * Purpose: Receive UDP client requests, build an authorization request * structure, and attach attribute-value pairs contained in * the request to the new structure. * *************************************************************************/AUTH_REQ *radrecv(UINT4 host,u_short udp_port,char* secret,u_char* buffer,int length){ u_char *ptr; AUTH_HDR *auth; int totallen; int attribute; int attrlen; int vendor; int vsa; int vsattrlen; DICT_ATTR *attr; UINT4 lvalue; VALUE_PAIR *first_pair; VALUE_PAIR *prev; VALUE_PAIR *pair; AUTH_REQ *authreq; if (length < AUTH_HDR_LEN) { /* too short to be real */ log_err("radrecv: runt packet of %d bytes from %s/%d\n", length, ipaddr2strp(host), udp_port); return ((AUTH_REQ *)NULL); } /* * Pre-allocate the new request data structure */ authreq = reqalloc("radrecv"); auth = (AUTH_HDR *)buffer; totallen = ntohs(auth->length); if (totallen > length) { /* truncated packet, ignore */ log_err("radrecv: message from %s/%d claimed length %d, only %d bytes received\n", ipaddr2strp(host), udp_port, totallen, length); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } debug("message received from %s/%d.%d code=%d, length=%d\n", ipaddr2strp(host), udp_port, auth->id, auth->code, totallen); if (debug_flag > 1) { hexdump((u_char*)buffer,totallen); } /* * Fill header fields */ authreq->ipaddr = host; authreq->udp_port = udp_port; authreq->id = auth->id; authreq->code = auth->code; memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN); strncpy(authreq->secret,secret,20); authreq->secret[19]='\0'; /* * Extract attribute-value pairs */ ptr = auth->data; length = totallen - AUTH_HDR_LEN; first_pair = (VALUE_PAIR *)NULL; prev = (VALUE_PAIR *)NULL; while(length > 0) { attribute = *ptr++; attrlen = *ptr++; if(attrlen < 2) { length = 0; continue; } attrlen -= 2; if ( attrlen > AUTH_STRING_LEN ) { log_err("radrecv: attribute %d from %s too long, length of %d > %d\n", attribute, req2strp(authreq), attrlen, AUTH_STRING_LEN); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } pair = pairalloc("radrecv"); if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) { snprintf(pair->name,(size_t)ID_LENGTH,"Unknown-%d",attribute); pair->attribute = attribute; pair->type = PW_TYPE_STRING; } else { strncpy(pair->name, attr->name, VALUE_PAIR_NAME_LEN-1); pair->name[VALUE_PAIR_NAME_LEN-1]='\0'; pair->attribute = attr->value; pair->type = attr->type; } if (pair->attribute == PW_VENDOR) { if (attrlen < 6) { pair->vendor = 0; pair->vsattribute = 0; pair->type = PW_TYPE_STRING; } else { memcpy(&vendor, ptr, sizeof(int)); vendor = ntohl(vendor); ptr += 4; vsattrlen = *ptr; if ( vendor == VENDOR_USROBOTICS ) { if (attrlen < 8) { pair->vendor = 0; pair->vsattribute = 0; pair->type = PW_TYPE_STRING; } else { memcpy(&vsa, ptr, sizeof(int)); vsa = ntohl(vsa); ptr += 4; attrlen -= 8; length -= 8; } } else { vsa = *ptr; ptr += 2; attrlen -= 6; length -= 6; } pair->vendor = vendor; pair->vsattribute = vsa; if((attr = dict_vsattrget(vendor,vsa)) != NULL) { strncpy(pair->name, attr->name, VALUE_PAIR_NAME_LEN-1); pair->name[VALUE_PAIR_NAME_LEN-1]='\0'; pair->type = attr->type; } else { log_debug("Attribute %d for vendor %d not found\n",vsa,vendor); snprintf(pair->name,(size_t)ID_LENGTH,"Vendor-Specific-%d-%d",vendor,vsa); pair->type = PW_TYPE_STRING; } } } switch(pair->type) {#if defined(ASCEND_BINARY) case PW_TYPE_ABINARY:#endif case PW_TYPE_STRING: memcpy(pair->strvalue, ptr, attrlen); pair->strvalue[attrlen] = '\0'; pair->lvalue = attrlen; debug_pair(pair); if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: memcpy(&lvalue, ptr, sizeof(UINT4)); pair->lvalue = ntohl(lvalue); debug_pair(pair); if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; default: debug(" %s (Unknown Type %d)\n", attr->name,attr->type); pairfree(pair,"radrecv"); break; } ptr += attrlen; length -= attrlen + 2; } authreq->request = first_pair; authreq->timestamp = now; /* now was set in main() */ /* copy the packet */ authreq->packet = bufalloc(totallen,"radrecv"); memcpy(authreq->packet,buffer,totallen); return(authreq);}/************************************************************************* * * Function: radrespond * * Purpose: Respond to supported requests * * PW_AUTHENTICATION_REQUEST - Authentication request from * a client network access server. * *************************************************************************/void radrespond(AUTH_REQ *authreq,int activefd){ if (authreq == (AUTH_REQ *)NULL) { return; } switch(authreq->code) { case PW_AUTHENTICATION_REQUEST: if(spawn_flag) { rad_spawn_child(authreq, activefd); } else { rad_authenticate(authreq, activefd); } break; default: log_err("unknown request type %d from %s ignored\n", authreq->code, req2strp(authreq)); reqfree(authreq,"radrespond"); break; }}/************************************************************************* * * Function: rad_spawn_child * * Purpose: Spawns child processes to perform password authentication * and respond to RADIUS clients. This functions also * cleans up complete child requests, and verifies that there * is only one process responding to each request (duplicate * requests are filtered out. * *************************************************************************/int rad_spawned_child_pid;void rad_spawn_child(AUTH_REQ *authreq,int activefd){ AUTH_REQ *curreq; AUTH_REQ *prevreq; UINT4 curtime; int request_count; int child_pid;#ifdef SMARTCARD key_t msg_key; int msg_id;#endif curtime = authreq->timestamp; request_count = 0; curreq = first_request; prevreq = (AUTH_REQ *)NULL; while(curreq != (AUTH_REQ *)NULL) { if(curreq->child_pid == -1 && curreq->timestamp + CLEANUP_DELAY <= curtime) { /* Request completed, delete it */ if(prevreq == (AUTH_REQ *)NULL) { first_request = curreq->next; reqfree(curreq,"rad_spawn_child"); curreq = first_request; } else { prevreq->next = curreq->next; reqfree(curreq,"rad_spawn_child"); curreq = prevreq->next; } } else if(curreq->ipaddr == authreq->ipaddr && curreq->udp_port == authreq->udp_port && curreq->id == authreq->id) { /* This is a duplicate request - just drop it */ log_err("dropping duplicate request from %s\n", req2strp(authreq)); reqfree(authreq,"rad_spawn_child"); return; } else { if(curreq->timestamp + max_request_time <= curtime && curreq->child_pid != -1) { /* This request seems to have hung - kill it */ child_pid = curreq->child_pid; log_err("sending SIGHUP to unresponsive child process %d\n", child_pid); curreq->child_pid = -1; kill(child_pid, SIGHUP);#ifdef SMARTCARD /* * delete childs message queue */ msg_key = RADIUS_MSG_KEY(child_pid); if ((msg_id = msgget(msg_key, 0600)) != -1) { msgctl(msg_id, IPC_RMID, 0); }#endif /* SMARTCARD */ } prevreq = curreq; curreq = curreq->next; request_count++; } } /* This is a new request */ if(request_count > max_requests) { request_count--; log_err("dropping request from %s; %d requests already in queue\n", req2strp(authreq), request_count); reqfree(authreq,"rad_spawn_child"); return; } /* Add this request to the list */ /* authreq->timestamp already set by radrecv */ authreq->next = (AUTH_REQ *)NULL; authreq->child_pid = -1; if(prevreq == (AUTH_REQ *)NULL) { first_request = authreq; } else { prevreq->next = authreq; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -