📄 rlm_pap.c
字号:
* modules, copy Cleartext-Password to User-Password */ if (cleartext_pw && !user_pw) { vp = paircreate(PW_USER_PASSWORD, PW_TYPE_STRING); if (!vp) return RLM_MODULE_FAIL; memcpy(vp, cleartext_pw, sizeof(*vp)); vp->next = NULL; pairadd(&request->config_items, vp); } /* * Don't touch existing Auth-Types. */ if (auth_type) { DEBUG2("rlm_pap: Found existing Auth-Type, not changing it."); return RLM_MODULE_NOOP; } /* * Can't do PAP if there's no password. */ if (!request->password || (request->password->attribute != PW_USER_PASSWORD)) { /* * Don't print out debugging messages if we know * they're useless. */ if (request->packet->code == PW_ACCESS_CHALLENGE) { return RLM_MODULE_NOOP; } DEBUG2("rlm_pap: No clear-text password in the request. Not performing PAP."); return RLM_MODULE_NOOP; } vp = paircreate(PW_AUTH_TYPE, PW_TYPE_INTEGER); if (!vp) return RLM_MODULE_FAIL; pairparsevalue(vp, inst->name); pairadd(&request->config_items, vp); return RLM_MODULE_UPDATED;}/* * Authenticate the user via one of any well-known password. */static int pap_authenticate(void *instance, REQUEST *request){ rlm_pap_t *inst = instance; VALUE_PAIR *vp; VALUE_PAIR *module_fmsg_vp; char module_fmsg[MAX_STRING_LEN]; MD5_CTX md5_context; SHA1_CTX sha1_context; uint8_t digest[40]; char buff[MAX_STRING_LEN]; char buff2[MAX_STRING_LEN + 50]; int scheme = PAP_ENC_INVALID; if (!request->password){ radlog(L_AUTH, "rlm_pap: Attribute \"Password\" is required for authentication."); return RLM_MODULE_INVALID; } /* * Clear-text passwords are the only ones we support. */ if (request->password->attribute != PW_USER_PASSWORD) { radlog(L_AUTH, "rlm_pap: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name); return RLM_MODULE_INVALID; } /* * The user MUST supply a non-zero-length password. */ if (request->password->length == 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: empty password supplied"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); return RLM_MODULE_INVALID; } DEBUG("rlm_pap: login attempt with password %s", request->password->strvalue); /* * First, auto-detect passwords, by attribute in the * config items. */ if ((inst->sch == PAP_ENC_AUTO) || inst->auto_header) { for (vp = request->config_items; vp != NULL; vp = vp->next) { switch (vp->attribute) { case PW_USER_PASSWORD: /* deprecated */ case PW_CLEARTEXT_PASSWORD: /* preferred */ goto do_clear; case PW_CRYPT_PASSWORD: goto do_crypt; case PW_MD5_PASSWORD: goto do_md5; case PW_SHA_PASSWORD: goto do_sha; case PW_NT_PASSWORD: goto do_nt; case PW_LM_PASSWORD: goto do_lm; case PW_SMD5_PASSWORD: goto do_smd5; case PW_SSHA_PASSWORD: goto do_ssha; case PW_NS_MTA_MD5_PASSWORD: goto do_ns_mta_md5; default: break; /* ignore it */ } } fail: DEBUG("rlm_pap: No password configured for the user. Cannot do authentication"); return RLM_MODULE_FAIL; } else { vp = NULL; if (inst->sch == PAP_ENC_CRYPT) { vp = pairfind(request->config_items, PW_CRYPT_PASSWORD); } /* * Old-style: all passwords are in User-Password. */ if (!vp) { vp = pairfind(request->config_items, PW_USER_PASSWORD); if (!vp) goto fail; } scheme = inst->sch; } /* * Now that we've decided what to do, go do it. */ switch (scheme) { case PAP_ENC_CLEAR: do_clear: DEBUG("rlm_pap: Using clear text password \"%s\".", vp->strvalue); if (strcmp((char *) vp->strvalue, (char *) request->password->strvalue) != 0){ snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: CLEAR TEXT password check failed"); goto make_msg; } done: DEBUG("rlm_pap: User authenticated successfully"); return RLM_MODULE_OK; break; case PAP_ENC_CRYPT: do_crypt: DEBUG("rlm_pap: Using CRYPT encryption."); if (lrad_crypt_check((char *) request->password->strvalue, (char *) vp->strvalue) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: CRYPT password check failed"); goto make_msg; } goto done; break; case PW_MD5_PASSWORD: do_md5: DEBUG("rlm_pap: Using MD5 encryption."); normify(vp, 16); if (vp->length != 16) { DEBUG("rlm_pap: Configured MD5 password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured MD5 password has incorrect length"); goto make_msg; } MD5Init(&md5_context); MD5Update(&md5_context, request->password->strvalue, request->password->length); MD5Final(digest, &md5_context); if (memcmp(digest, vp->strvalue, vp->length) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: MD5 password check failed"); goto make_msg; } goto done; break; case PW_SMD5_PASSWORD: do_smd5: DEBUG("rlm_pap: Using SMD5 encryption."); normify(vp, 16); if (vp->length <= 16) { DEBUG("rlm_pap: Configured SMD5 password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured SMD5 password has incorrect length"); goto make_msg; } MD5Init(&md5_context); MD5Update(&md5_context, request->password->strvalue, request->password->length); MD5Update(&md5_context, &vp->strvalue[16], vp->length - 16); MD5Final(digest, &md5_context); /* * Compare only the MD5 hash results, not the salt. */ if (memcmp(digest, vp->strvalue, 16) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SMD5 password check failed"); goto make_msg; } goto done; break; case PW_SHA_PASSWORD: do_sha: DEBUG("rlm_pap: Using SHA1 encryption."); normify(vp, 20); if (vp->length != 20) { DEBUG("rlm_pap: Configured SHA1 password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured SHA1 password has incorrect length"); goto make_msg; } SHA1Init(&sha1_context); SHA1Update(&sha1_context, request->password->strvalue, request->password->length); SHA1Final(digest,&sha1_context); if (memcmp(digest, vp->strvalue, vp->length) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SHA1 password check failed"); goto make_msg; } goto done; break; case PW_SSHA_PASSWORD: do_ssha: DEBUG("rlm_pap: Using SSHA encryption."); normify(vp, 20); if (vp->length <= 20) { DEBUG("rlm_pap: Configured SSHA password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured SHA password has incorrect length"); goto make_msg; } SHA1Init(&sha1_context); SHA1Update(&sha1_context, request->password->strvalue, request->password->length); SHA1Update(&sha1_context, &vp->strvalue[20], vp->length - 20); SHA1Final(digest,&sha1_context); if (memcmp(digest, vp->strvalue, 20) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SSHA password check failed"); goto make_msg; } goto done; break; case PW_NT_PASSWORD: do_nt: DEBUG("rlm_pap: Using NT encryption."); normify(vp, 16); if (vp->length != 16) { DEBUG("rlm_pap: Configured NT-Password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured NT-Password has incorrect length"); goto make_msg; } sprintf(buff2,"%%{mschap:NT-Hash %s}", request->password->strvalue); if (!radius_xlat(digest,sizeof(digest),buff2,request,NULL)){ DEBUG("rlm_pap: mschap xlat failed"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: mschap xlat failed"); goto make_msg; } if ((lrad_hex2bin(digest, digest, 16) != vp->length) || (memcmp(digest, vp->strvalue, vp->length) != 0)) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: NT password check failed"); goto make_msg; } goto done; break; case PW_LM_PASSWORD: do_lm: DEBUG("rlm_pap: Using LM encryption."); normify(vp, 16); if (vp->length != 16) { DEBUG("rlm_pap: Configured LM-Password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured LM-Password has incorrect length"); goto make_msg; } sprintf(buff2,"%%{mschap:LM-Hash %s}", request->password->strvalue); if (!radius_xlat(digest,sizeof(digest),buff2,request,NULL)){ DEBUG("rlm_pap: mschap xlat failed"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: mschap xlat failed"); goto make_msg; } if ((lrad_hex2bin(digest, digest, 16) != vp->length) || (memcmp(digest, vp->strvalue, vp->length) != 0)) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: LM password check failed"); make_msg: DEBUG("rlm_pap: Passwords don't match"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); return RLM_MODULE_REJECT; } goto done; break; case PAP_ENC_NS_MTA_MD5: do_ns_mta_md5: DEBUG("rlm_pap: Using NT-MTA-MD5 password"); if (vp->length != 64) { DEBUG("rlm_pap: Configured NS-MTA-MD5-Password has incorrect length"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured NS-MTA-MD5-Password has incorrect length"); goto make_msg; } /* * Sanity check the value of NS-MTA-MD5-Password */ if (lrad_hex2bin(vp->strvalue, buff, 32) != 16) { DEBUG("rlm_pap: Configured NS-MTA-MD5-Password has invalid value"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured NS-MTA-MD5-Password has invalid value"); goto make_msg; } /* * Ensure we don't have buffer overflows. * * This really: sizeof(buff) - 2 - 2*32 - strlen(passwd) */ if (strlen(request->password->strvalue) >= (sizeof(buff2) - 2 - 2 * 32)) { DEBUG("rlm_pap: Configured password is too long"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: password is too long"); goto make_msg; } /* * Set up the algorithm. */ { char *p = buff2; memcpy(p, &vp->strvalue[32], 32); p += 32; *(p++) = 89; strcpy(p, request->password->strvalue); p += strlen(p); *(p++) = 247; memcpy(p, &vp->strvalue[32], 32); p += 32; MD5Init(&md5_context); MD5Update(&md5_context, buff2, p - buff2); MD5Final(digest, &md5_context); } if (memcmp(digest, buff, 16) != 0) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: NS-MTA-MD5 password check failed"); goto make_msg; } goto done; default: break; } DEBUG("rlm_pap: No password configured for the user. Cannot do authentication"); return RLM_MODULE_FAIL;}/* * The module name should be the only globally exported symbol. * That is, everything else should be 'static'. * * If the module needs to temporarily modify it's instantiation * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE. * The server will then take care of ensuring that the module * is single-threaded. */module_t rlm_pap = { "PAP", 0, /* type */ NULL, /* initialization */ pap_instantiate, /* instantiation */ { pap_authenticate, /* authentication */ pap_authorize, /* authorization */ NULL, /* preaccounting */ NULL, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ }, pap_detach, /* detach */ NULL, /* destroy */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -