📄 radiusd.c
字号:
/* * Check to see if we have a CHAP password. */ else if ((auth_item = get_attribute(authreq->request, PW_CHAP_PASSWORD)) != (VALUE_PAIR *)NULL) { /* Use MD5 to verify */ ptr = string; *ptr++ = *auth_item->strvalue; strcpy(ptr, password_item->strvalue); ptr += strlen(password_item->strvalue); if ((challenge = get_attribute(authreq->request, PW_CHAP_CHALLENGE)) != (VALUE_PAIR *)NULL) { chlen = challenge->lvalue; memcpy(ptr, challenge->strvalue, chlen); } else { chlen = AUTH_VECTOR_LEN; memcpy(ptr, authreq->vector, chlen); } md5_calc(pw_digest, string, 1 + chlen + strlen(password_item->strvalue)); /* Compare them */ if(memcmp(pw_digest, auth_item->strvalue + 1, CHAP_VALUE_LENGTH) != 0) { result = -1; } else { result = 0; } } else if (strcmp(password_item->strvalue, string) == 0) { result = 0; } else { result = -1; } break; case PW_AUTHTYPE_UNIX: if(unix_pass(auth_name, string, callfrom) != 0) { result = -1; } break;#ifdef SECURID case PW_AUTHTYPE_SECURID: if(pass != (char *)NULL) { pairfree(user_check,"rad_authenticate"); return( securid(auth_name, string, authreq, user_reply, activefd) ); } else { result = -1; } break;#endif /* SECURID */ case PW_AUTHTYPE_CRYPT: /* password is stored encrypted in string */ if(password_item == (VALUE_PAIR *)NULL) { if(string[0] != '\0') { result = -1; } } else if (pass != NULL) { encpw = (char*)crypt(string,password_item->strvalue); if(strcmp(encpw,password_item->strvalue) != 0) { result = -1; } } else { result = -1; } break; case PW_AUTHTYPE_REJECT: result = -1; break;#if defined(PAM) && defined(HAVE_LIBPAM) case PW_AUTHTYPE_PAM: if (usepamauth) { if (unix_pam(auth_name, string, pam_auth) != 0) { result = -1; user_msg = (char *)NULL; } } else { log_err("PAM auth not enabled. Please re-run daemon with the correct argument"); user_msg = (char *)NULL; result=-1; } break;#endif#ifdef ACTIVCARD case PW_AUTHTYPE_ACTIVCARD: if (pass != (char *)NULL) { pairfree(user_check,"rad_authenticate"); /* activcard calls send_*() as needed */ return ( activcard_auth(auth_name, string, authreq, user_reply, activefd) ); } else { result = -1; } break;#endif /* ACTIVCARD */ case PW_AUTHTYPE_NONE: /* No Password or Auth-Type found in check-items */ debug("entry for user \"%s\" has no Password or Auth-Type check-item\n",authreq->name); result = 0; break; default: log_err("Warning: entry for user \"%s\" has unknown Auth-Type = %d\n",authreq->name, authtype); result = -1; break; } } if(result != 0) { send_reject(authreq, user_msg, activefd); } else { send_accept(authreq, user_reply, user_msg, activefd); } reqfree(authreq,"rad_authenticate"); pairfree(user_check,"rad_authenticate"); pairfree(user_reply,"rad_authenticate"); return(0);}/************************************************************************* * * Function: send_reject * * Purpose: Reply to the request with a REJECT. Also attach * any user message provided. * *************************************************************************/void send_reject(AUTH_REQ *authreq,char *msg,int activefd){ u_char code; int total_length; code = PW_AUTHENTICATION_REJECT; report[RR_REJECT]++; debug("sending reject to %s\n", req2strp(authreq)); total_length = build_packet(authreq,(VALUE_PAIR *)NULL,msg,code, FW_REPLY,send_buffer,sizeof(send_buffer)); /* Send it to the user */ send_packet(activefd, authreq->ipaddr, authreq->udp_port, (u_char*)send_buffer, total_length);}/************************************************************************* * * Function: send_challenge * * Purpose: Reply to the request with a CHALLENGE. Also attach * any user message provided and a state value. * *************************************************************************/void send_challenge(AUTH_REQ *authreq,char *msg,char *state,int activefd){ VALUE_PAIR *reply; int len; int total_length; report[RR_CHALLENGE]++; if((state != (char *)NULL) && ((len=strlen(state)) > (size_t)0)) { reply = pairalloc("send_challenge"); memcpy(reply->name,"State",5); reply->attribute = PW_STATE; reply->type = PW_TYPE_STRING; if (len > AUTH_STRING_LEN) { len = AUTH_STRING_LEN; } reply->lvalue = len; memcpy(reply->strvalue,state,len); } else { reply = (VALUE_PAIR *)NULL; } debug("sending challenge to %s\n", req2strp(authreq)); total_length = build_packet(authreq,reply,msg,PW_ACCESS_CHALLENGE,FW_REPLY,send_buffer,sizeof(send_buffer)); send_packet(activefd,authreq->ipaddr,authreq->udp_port,send_buffer,total_length); }/************************************************************************* * * Function: send_accept * * Purpose: Reply to the request with an ACKNOWLEDGE. Also attach * reply attribute value pairs and any user message provided. * *************************************************************************/void send_accept(AUTH_REQ *authreq,VALUE_PAIR *reply,char *msg,int activefd){ VALUE_PAIR *menu_attr; char state_value[120]; int total_length; /* Check to see if the response is a menu */ if((menu_attr = get_attribute(reply, PW_MENU)) != (VALUE_PAIR *)NULL) { msg = get_menu(menu_attr->strvalue); snprintf(state_value,sizeof(state_value),"MENU=%s", menu_attr->strvalue); send_challenge(authreq, msg, state_value, activefd); return; } report[RR_ACCEPT]++; debug("sending accept to %s\n", req2strp(authreq)); total_length = build_packet(authreq,reply,msg,PW_AUTHENTICATION_ACK,FW_REPLY,send_buffer,sizeof(send_buffer)); /* Send it to the user */ send_packet(activefd, authreq->ipaddr, authreq->udp_port, (u_char*)send_buffer, total_length);}/************************************************************************* * * Function: build_packet * * Purpose: called by routines to build RADIUS packet * * forward = 0 FW_REPLY replying to client * 1 FW_SERVER forwarding request to remote server * 2 FW_CLIENT forwarding response to client * *************************************************************************/int build_packet(AUTH_REQ*authreq,VALUE_PAIR*reply,char*msg,u_char code,int forward,u_char*buffer,size_t buflen ){ AUTH_HDR *auth; VALUE_PAIR *item; u_short total_length; u_char *ptr; u_char *lptr; int len; UINT4 lvalue; UINT4 vendor; u_char digest[16]; int secretlen; int block_len; auth = (AUTH_HDR *)buffer; /* Build standard header */ auth->code = code; auth->id = authreq->id; total_length = AUTH_HDR_LEN; /* Load up the configuration values for the user */ ptr = auth->data; while(reply != (VALUE_PAIR *)NULL) { debug_pair(reply); *ptr++ = reply->attribute; lptr = ptr; if (reply->attribute == PW_VENDOR && reply->vendor != 0) { ptr++; total_length += 6; vendor = htonl(reply->vendor); memcpy(ptr,&vendor,sizeof(UINT4)); ptr += 4; *ptr++ = reply->vsattribute; if (reply->type == PW_TYPE_STRING) { *lptr = reply->lvalue + 8; } else { *lptr = 12; } } switch(reply->type) {#if defined(ASCEND_BINARY) case PW_TYPE_ABINARY:#endif case PW_TYPE_STRING: len = reply->lvalue; if (len > AUTH_STRING_LEN) { len = AUTH_STRING_LEN; } *ptr++ = len + 2; memcpy(ptr, reply->strvalue,len); ptr += len; total_length += len + 2; break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: *ptr++ = sizeof(UINT4) + 2; lvalue = htonl(reply->lvalue); memcpy(ptr, &lvalue, sizeof(UINT4)); ptr += sizeof(UINT4); total_length += sizeof(UINT4) + 2; break; default: break; } reply = reply->next; } /* Append the user message */ if(msg != (char *)NULL && (len = strlen(msg)) > 0) { while(len > 0) { if(len > AUTH_STRING_LEN) { block_len = AUTH_STRING_LEN; } else { block_len = len; } *ptr++ = PW_PORT_MESSAGE; *ptr++ = block_len + 2; memcpy(ptr, msg, block_len); msg += block_len; ptr += block_len; total_length += block_len + 2; len -= block_len; } } /* Copy over any proxy-states, in order */ if (forward == FW_REPLY) { item = authreq->request; while (item != (VALUE_PAIR *)NULL) { if (item->attribute == PW_PROXY) { debug_pair(item); *ptr++ = PW_PROXY; len = item->lvalue; *ptr++ = len + 2; memcpy(ptr,item->strvalue,len); ptr += len; total_length += len + 2; } item = item->next; } } auth->length = htons(total_length); if (code == PW_AUTHENTICATION_ACK || code == PW_AUTHENTICATION_REJECT || code == PW_ACCESS_CHALLENGE || code == PW_ACCOUNTING_RESPONSE) { /* The Authenticator field in an Response packet is called the Response Authenticator, and contains a one-way MD5 hash calculated over a stream of octets consisting of the Response Code, Identifier, Length, the Request Authenticator field from the Request packet being replied to, and the response attributes if any, followed by the shared secret. The resulting 16 octet MD5 hash value is stored in the Authenticator field of the Response packet. */ /* Append secret and calculate the response digest */ memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN); secretlen = strlen((const char *)authreq->secret); if ((size_t)(total_length+secretlen)<=buflen) { memcpy(buffer + total_length, authreq->secret, secretlen); md5_calc(digest, (u_char *)auth, total_length + secretlen); memcpy(auth->vector, digest, AUTH_VECTOR_LEN); memset(buffer + total_length, 0, secretlen); } else { log_err("build_packet: execeeding buffer size"); } } else if (code == PW_ACCOUNTING_REQUEST) { /* Forwarding */ memset(auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen(authreq->forw_secret); if ((size_t)(total_length+secretlen)<=buflen) { memcpy(buffer + total_length, authreq->forw_secret, secretlen); md5_calc(digest, buffer, total_length + secretlen); memcpy(auth->vector,digest,AUTH_VECTOR_LEN); memset(buffer + total_length, 0, secretlen); } else { log_err("build_packet: execeeding buffer size"); } } else if (code == PW_AUTHENTICATION_REQUEST) { /* Forwarding */ memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN); } return ((int)total_length);}/************************************************************************* * * Function: decrypt_password * * Purpose: decrypts the User-Password attribute in place in * authreq->request using authreq->vector and * secret and the algorithm specified in the * RADIUS RFC, and returns a pointer to the Password * if successful, otherwise NULL * *************************************************************************/char * decrypt_password(AUTH_REQ *authreq,char *secret){ VALUE_PAIR *auth_item; int i; int j; int passlen; char hold_vector[AUTH_VECTOR_LEN]; char pw_digest[16]; char *string; char *ptr; calc_digest(pw_digest, authreq, secret); /* * Decrypt the password in the request. */ if((auth_item = get_attribute(authreq->request, PW_PASSWORD)) == (VALUE_PAIR *)NULL) { return (char *)NULL; } passlen = auth_item->lvalue; if(passlen > AUTH_MAXPASS_LEN) { log_err("decrypt_password: Password length %d > %d max not allowed\n",passlen, AUTH_MAXPASS_LEN); passlen = AUTH_MAXPASS_LEN; } string = auth_item->strvalue; ptr = string; for(i = 0;i < passlen;i += AUTH_PASS_LEN) { /* * Store the vector to be used in next segment * of the encrypted password. */ memcpy(hold_vector, ptr, AUTH_VECTOR_LEN); /* Decrypt from the digest */ for(j = 0;j < AUTH_PASS_LEN;j++) { *ptr ^= pw_digest[j]; ptr++; } /* Calculate the next digest if necessary */ if(i + AUTH_PASS_LEN < passlen) { calc_next_digest((u_char*)pw_digest, (u_char*)secret, (u_char*)hold_vector); } } *ptr = '\0'; /* this depends on the fact that auth_item->strvalue always has an extra byte available */ return string;}/************************************************************************* * * Function: encrypt_password * * Purpose: encrypts the User-Password attribute in place in * authreq->request using authreq->vector and * secret and the algorithm specified in the * RADIUS RFC, and returns a pointer to the Password * if successful, otherwise NULL * *************************************************************************/char * encrypt_password(AUTH_REQ *authreq,char *secret){ VALUE_PAIR *auth_item; int i; int j;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -