⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otp_mppe.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: otp_mppe.c,v 1.4 2007/11/23 13:46:56 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2001,2002  Google, Inc. * Copyright 2005,2006 TRI-D Systems, Inc. */#include <freeradius-devel/ident.h>RCSID("$Id: otp_mppe.c,v 1.4 2007/11/23 13:46:56 aland Exp $")/* avoid inclusion of these FR headers which conflict w/ OpenSSL */#define _FR_MD4_H#define _FR_SHA1_H#include <freeradius-devel/rad_assert.h>#include "extern.h"#include "otp.h"#include "otp_mppe.h"#include <openssl/des.h>#include <openssl/md4.h>#include <openssl/md5.h>#include <openssl/sha.h>#include <string.h>/* * Add MPPE attributes to a request, if required. */voidotp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,         const char *passcode){  VALUE_PAIR **avp = &request->reply->vps;  VALUE_PAIR *cvp, *rvp, *vp;  cvp = pairfind(request->packet->vps, pwattr[pwe - 1]);  rvp = pairfind(request->packet->vps, pwattr[pwe]);  switch (pwe) {  case PWE_PAP:  case PWE_CHAP:    return;  case PWE_MSCHAP:    /* First, set some related attributes. */    vp = pairmake("MS-MPPE-Encryption-Policy",                  otp_mppe_policy[opt->mschap_mppe_policy], T_OP_EQ);    rad_assert(vp != NULL);    pairadd(avp, vp);    vp = pairmake("MS-MPPE-Encryption-Types",                  otp_mppe_types[opt->mschap_mppe_types], T_OP_EQ);    rad_assert(vp != NULL);    pairadd(avp, vp);    /* If no MPPE, we're done. */    if (!opt->mschap_mppe_policy)      return;    /*     * Generate the MS-CHAP-MPPE-Keys attribute.  This is not specified     * anywhere -- RFC 2548, par. 2.4.1 is the authority but it has     * typos and omissions that make this unimplementable.  The     * code here is based on experimental results provided by     * Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp>.     * We only support 128-bit keys derived from the NT hash; 40-bit     * and 56-bit keys are derived from the LM hash, which besides     * being deprecated, has severe security problems.     */    {      size_t i, passcode_len;      unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];      unsigned char password_md[MD4_DIGEST_LENGTH];      unsigned char mppe_keys[32];      /*                    0x    ASCII(mppe_keys)      '\0' */      char mppe_keys_string[2 + (2 * sizeof(mppe_keys)) + 1];      /* Zero the LM-Key sub-field (and padding). */      (void) memset(mppe_keys, 0, sizeof(mppe_keys));      /*       * The NT-Key sub-field is MD4(MD4(unicode(password))).       * Start by hashing the unicode passcode.       * This is broken because unicode chars are machine-ordered,       * but the spec (RFC 2433) doesn't say how to prepare       * the password for md4 (other than by example values).       */      passcode_len = strlen(passcode);      for (i = 0; i < passcode_len; ++i) {        /* Set the high order 8 bits to 0 (little-endian) */        password_unicode[i * 2] = *passcode++;        password_unicode[i * 2 + 1] = 0;      }      /* first md4 */      (void) MD4(password_unicode, 2 * passcode_len, password_md);      /* second md4 */      (void) MD4(password_md, MD4_DIGEST_LENGTH, &mppe_keys[8]);#if 0 /* encoding now handled in lib/radius.c:rad_pwencode() */      {        unsigned char md5_md[MD5_DIGEST_LENGTH];        unsigned char encode_buf[AUTH_VECTOR_LEN + MAX_STRING_LEN];        int secretlen;        /* Now we must encode the key as User-Password is encoded. */        secretlen = strlen(request->secret);        (void) memcpy(encode_buf, request->secret, secretlen);        (void) memcpy(encode_buf + secretlen, request->packet->vector,                      AUTH_VECTOR_LEN);        (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN, md5_md);        for (i = 0; i < 16; ++i)          mppe_keys[i] ^= md5_md[i];        (void) memcpy(encode_buf + secretlen, mppe_keys, MD5_DIGEST_LENGTH);        (void) MD5(encode_buf, secretlen + MD5_DIGEST_LENGTH, md5_md);        for (i = 0; i < 16; ++i)          mppe_keys[i + 16] ^= md5_md[i];      }#endif /* 0 */      /* Whew.  Now stringify it for pairmake(). */      mppe_keys_string[0] = '0';      mppe_keys_string[1] = 'x';      for (i = 0; i < 32; ++i)        (void) sprintf(&mppe_keys_string[i*2+2], "%02X", mppe_keys[i]);      vp = pairmake("MS-CHAP-MPPE-Keys", mppe_keys_string, T_OP_EQ);      rad_assert(vp != NULL);      pairadd(avp, vp);    } /* (doing mppe) */  break; /* PWE_MSCHAP */  case PWE_MSCHAP2:  {    size_t i;    unsigned char password_md_md[MD4_DIGEST_LENGTH];    /*     * MS-CHAPv2 requires mutual authentication; we must prove     * that we know the secret.  This is a bit circuitous: set     * MD1 = SHA(MD4(MD4(unicode(password)))|NT_RESPONSE|MAGIC1),     * MD2 = MSB8(SHA(PEER_CHALLENGE|MS_CHAP_CHALLENGE|USERNAME)),     * and finally use SHA(MD1|MD2|MAGIC2) as the authenticator.     * The authenticator is returned as the string "S=<auth>",     * <auth> is the authenticator expressed as [uppercase] ASCII.     * See RFC 2759.     */    {      size_t passcode_len;      unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];      unsigned char password_md[MD4_DIGEST_LENGTH];      SHA_CTX ctx;      unsigned char md1[SHA_DIGEST_LENGTH];      unsigned char md2[SHA_DIGEST_LENGTH];      unsigned char auth_md[SHA_DIGEST_LENGTH];      /*                  S=  (  ASCII(auth_md)   )  \0 */      char auth_md_string[2 + (2 * sizeof(auth_md)) + 1];      /*       * ugh.  The ASCII authenticator (auth_md_string) is sent       * along with a single (useless) binary byte (the ID).       * So we must "stringify" it again (for pairmake()) since the       * binary byte requires the attribute to be of type "octets".       */      /*                    0x  (ID) ( ASCII("S="ASCII(auth_md))) */      char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];      char *username = request->username->vp_strvalue;      int username_len = request->username->length;      /* "Magic server to client signing constant" */      unsigned char magic1[39] =        { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,          0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,          0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,          0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };      /* "Pad to make it do more than one iteration" */      unsigned char magic2[41] =        { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,          0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,          0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,          0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,          0x6E };      /*       * Start by hashing the unicode passcode.       * This is broken because unicode chars are machine-ordered,       * but the spec (RFC 2759) doesn't say how to prepare       * the password for md4 (other than by example values).       */      passcode_len = strlen(passcode);      for (i = 0; i < passcode_len; ++i) {        /* Set the high order 8 bits to 0 (little-endian) */        password_unicode[i * 2] = *passcode++;        password_unicode[i * 2 + 1] = 0;      }      /* first md4 */      (void) MD4(password_unicode, 2 * passcode_len, password_md);      /* second md4 */      (void) MD4(password_md, MD4_DIGEST_LENGTH, password_md_md);      /* MD1 */      SHA1_Init(&ctx);      SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);      SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);      SHA1_Update(&ctx, magic1, sizeof(magic1));      SHA1_Final(md1, &ctx);      /* MD2 */      SHA1_Init(&ctx);      SHA1_Update(&ctx, rvp->vp_strvalue + 2, 16);      SHA1_Update(&ctx, cvp->vp_strvalue, 16);      SHA1_Update(&ctx, username, username_len);      SHA1_Final(md2, &ctx);      /* The Authenticator */      SHA1_Init(&ctx);      SHA1_Update(&ctx, md1, SHA_DIGEST_LENGTH);      SHA1_Update(&ctx, md2, 8);      SHA1_Update(&ctx, magic2, sizeof(magic2));      SHA1_Final(auth_md, &ctx);      /* String conversion. */      auth_md_string[0] = 'S';      auth_md_string[1] = '=';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -