diff options
Diffstat (limited to 'src/windows/wintel/auth.c')
-rw-r--r-- | src/windows/wintel/auth.c | 415 |
1 files changed, 235 insertions, 180 deletions
diff --git a/src/windows/wintel/auth.c b/src/windows/wintel/auth.c index f3956ac11b..6a7db72653 100644 --- a/src/windows/wintel/auth.c +++ b/src/windows/wintel/auth.c @@ -7,9 +7,6 @@ #ifdef KRB4 #include "kerberos.h" #endif -#include "telnet.h" -#include "telopts.h" - #ifdef KRB5 #include "krb5.h" #include "des_int.h" @@ -17,8 +14,11 @@ #include "los-proto.h" #endif +#include "telnet.h" +#include "telopts.h" + /* - * Contants + * Constants */ #define IS 0 #define SEND 1 @@ -40,7 +40,7 @@ #define K5_REJECT 1 #define K5_ACCEPT 2 - #define K5_RESPONSE 3 + #define K5_RESPONSE 3 // They had to make it different #define AUTH_WHO_MASK 1 #define AUTH_CLIENT_TO_SERVER 0 @@ -50,7 +50,7 @@ #define AUTH_HOW_ONE_WAY 0 #define AUTH_HOW_MUTUAL 2 - #ifndef KSUCCESS + #ifndef KSUCCESS // Let K5 use K4 constants #define KSUCCESS 0 #define KFAILURE 255 #endif @@ -59,14 +59,23 @@ */ #ifdef KRB4 static CREDENTIALS cred; + static KTEXT_ST auth; + #define KRB_SERVICE_NAME "rcmd" #define KERBEROS_VERSION KERBEROS_V4 + + static int k4_auth_send (void); #endif #ifdef KRB5 static krb5_data auth; static int auth_how; + static krb5_auth_context *auth_context; + #define KRB_SERVICE_NAME "host" #define KERBEROS_VERSION KERBEROS_V5 + + static int k5_auth_send (int how); + static int k5_auth_reply (int how, unsigned char *data, int cnt); #endif BOOL encrypt_enable; @@ -77,7 +86,8 @@ * Parameters: * enable - TRUE to enable, FALSE to disable. */ -static void auth_encrypt_enable( +static void +auth_encrypt_enable( BOOL enable) { encrypt_enable = enable; @@ -91,14 +101,16 @@ static void auth_encrypt_enable( * Parameters: * ks - kstream to send abort message to. */ -static void auth_abort( +static void +auth_abort( kstream ks, char *errmsg, long r) { char buf[9]; - wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, AUTH_NULL, AUTH_NULL, IAC, SE); + wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, AUTH_NULL, + AUTH_NULL, IAC, SE); TelnetSend(ks, (LPSTR)buf, 8, 0); if (errmsg != NULL) { @@ -114,7 +126,8 @@ static void auth_abort( #endif } - MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!", MB_OK | MB_ICONEXCLAMATION); + MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!", + MB_OK | MB_ICONEXCLAMATION); } } /* auth_abort */ @@ -126,7 +139,8 @@ static void auth_abort( * Parameters: * kstream - kstream to send abort message to. */ -static int copy_for_net( +static int +copy_for_net( unsigned char *to, unsigned char *from, int c) @@ -147,7 +161,7 @@ static int copy_for_net( } /* copy_for_net */ -/*+ +/*++ * Function: Parse authentication send command * * Parameters: @@ -160,7 +174,8 @@ static int copy_for_net( * * Returns: Kerberos error code. */ -static int auth_send( +static int +auth_send( kstream ks, unsigned char *parsedat, int end_sub) @@ -170,14 +185,6 @@ static int auth_send( int plen; int r; int i; - #ifdef KRB4 - KTEXT_ST auth; - char instance[INST_SZ]; - char *realm; - #endif /* KRB4 */ - #ifdef KRB5 - extern int kerberos5_send (int how); - #endif /* KRB5 */ auth_how = -1; @@ -195,57 +202,18 @@ static int auth_send( } #ifdef KRB4 - memset(instance, 0, sizeof(instance)); - - if (realm = krb_get_phost(szHostName)) - lstrcpy(instance, realm); - - realm = krb_realmofhost(szHostName); - - if (!realm) { - strcpy(buf, "Can't find realm for host \""); - strcat(buf, szHostName); - strcat(buf, "\""); - auth_abort(ks, buf, 0); - return KFAILURE; - } - - r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0); - - if (r == 0) - r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); - - if (r) { - strcpy(buf, "Can't get \""); - strcat(buf, KRB_SERVICE_NAME); - if (instance[0] != 0) { - strcat(buf, "."); - lstrcat(buf, instance); - } - strcat(buf, "@"); - lstrcat(buf, realm); - strcat(buf, "\" ticket"); - auth_abort(ks, buf, r); - return r; - } - - if (szUserName[0]) - pname = szUserName; - else - pname = cred.pname; - plen = strlen (szUserName); - + r = k4_auth_send (); #endif /* KRB4 */ #ifdef KRB5 - r = kerberos5_send (auth_how); - if (! r) - return KFAILURE; + r = k5_auth_send (auth_how); + #endif /* KRB5 */ - plen = strlen (szUserName); /* Set in kerberos_5 if needed */ - pname = szUserName; + if (! r) + return KFAILURE; - #endif /* KRB5 */ + plen = strlen (szUserName); // Set by k#_send if needed + pname = szUserName; wsprintf(buf, "%c%c%c%c", IAC, SB, AUTHENTICATION, NAME); memcpy (&buf[4], pname, plen); @@ -283,112 +251,25 @@ static int auth_send( * * Returns: Kerberos error code. */ -#ifdef KRB5 -static int auth_reply( +static int +auth_reply( kstream ks, unsigned char *parsedat, int end_sub) { - extern int kerberos5_reply (int how, unsigned char *data, int cnt); int n; - n = kerberos5_reply (0, parsedat, end_sub); + #ifdef KRB4 + n = k4_auth_reply (ks, parsedat, end_sub); + #endif + + #ifdef KRB5 + n = k5_auth_reply (auth_how, parsedat, end_sub); + #endif return n; } -#endif /* KRB5 */ -#ifdef KRB4 -static int auth_reply( - kstream ks, - unsigned char *parsedat, - int end_sub) -{ - time_t t; - int x; - char buf[512]; - int i; - des_cblock session_key; - des_key_schedule sched; - static des_cblock challenge; - - if (end_sub < 4) - return KFAILURE; - - if (parsedat[2] != KERBEROS_V4) - return KFAILURE; - - if (parsedat[4] == K4_REJECT) { - buf[0] = 0; - - for (i = 5; i <= end_sub; i++) { - if (parsedat[i] == IAC) - break; - buf[i-5] = parsedat[i]; - buf[i-4] = 0; - } - if (!buf[0]) - strcpy(buf, "Authentication rejected by remote machine!"); - MessageBox(HWND_DESKTOP, buf, NULL, MB_OK | MB_ICONEXCLAMATION); - - return KFAILURE; - } - - if (parsedat[4] == K4_ACCEPT) { - if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) - return KSUCCESS; - - if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) - return KFAILURE; - - des_key_sched(cred.session, sched); - - t = time(NULL); - memcpy(challenge, &t, 4); - memcpy(&challenge[4], &t, 4); - des_ecb_encrypt(&challenge, &session_key, sched, 1); - - /* - * Increment the challenge by 1, and encrypt it for - * later comparison. - */ - for (i = 7; i >= 0; --i) { - x = (unsigned int)challenge[i] + 1; - challenge[i] = x; /* ignore overflow */ - if (x < 256) /* if no overflow, all done */ - break; - } - - des_ecb_encrypt(&challenge, &challenge, sched, 1); - - wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, - KERBEROS_V4, AUTH_CLIENT_TO_SERVER|AUTH_HOW_MUTUAL, K4_CHALLENGE); - memcpy(&buf[7], session_key, 8); - wsprintf(&buf[15], "%c%c", IAC, SE); - TelnetSend(ks, (LPSTR)buf, 17, 0); - - return KSUCCESS; - } - - if (parsedat[4] == K4_RESPONSE) { - if (end_sub < 12) - return KFAILURE; - - if (memcmp(&parsedat[5], challenge, sizeof(challenge)) != 0) { - MessageBox(HWND_DESKTOP, "Remote machine is being impersonated!", - NULL, MB_OK | MB_ICONEXCLAMATION); - - return KFAILURE; - } - - return KSUCCESS; - } - - return KFAILURE; - -} /* auth_reply */ - -#endif /* KRB4 */ /*+ * Function: Parse the athorization sub-options and reply. * @@ -399,7 +280,8 @@ static int auth_reply( * * end_sub - last charcter position in parsedat. */ -void auth_parse( +void +auth_parse( kstream ks, unsigned char *parsedat, int end_sub) @@ -421,7 +303,8 @@ void auth_parse( * * data - user data. */ -int INTERFACE auth_init( +int INTERFACE +auth_init( kstream str, kstream_ptr data) { @@ -438,7 +321,8 @@ int INTERFACE auth_init( * * data - user data. */ -void INTERFACE auth_destroy( +void INTERFACE +auth_destroy( kstream str) { } /* auth_destroy */ @@ -456,7 +340,8 @@ void INTERFACE auth_destroy( * * Returns: number of characters converted. */ -int INTERFACE auth_encrypt( +int INTERFACE +auth_encrypt( struct kstream_data_block *out, struct kstream_data_block *in, kstream str) @@ -482,7 +367,8 @@ int INTERFACE auth_encrypt( * * Returns: number of characters converted. */ -int INTERFACE auth_decrypt( +int INTERFACE +auth_decrypt( struct kstream_data_block *out, struct kstream_data_block *in, kstream str) @@ -495,21 +381,183 @@ int INTERFACE auth_decrypt( } /* auth_decrypt */ -/*+*/ +/*++*/ +#ifdef KRB4 +/* +** +** K4_auth_send - gets authentication bits we need to send to KDC. +** +** Result is left in auth +** +** Returns: 0 on failure, 1 on success +*/ +static int +k4_auth_send () { + int r; // Return value + char instance[INST_SZ]; + char *realm; + + memset(instance, 0, sizeof(instance)); + + if (realm = krb_get_phost(szHostName)) + lstrcpy(instance, realm); + + realm = krb_realmofhost(szHostName); + + if (!realm) { + strcpy(buf, "Can't find realm for host \""); + strcat(buf, szHostName); + strcat(buf, "\""); + auth_abort(ks, buf, 0); + return KFAILURE; + } + + r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0); + + if (r == 0) + r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); + + if (r) { + strcpy(buf, "Can't get \""); + strcat(buf, KRB_SERVICE_NAME); + if (instance[0] != 0) { + strcat(buf, "."); + lstrcat(buf, instance); + } + strcat(buf, "@"); + lstrcat(buf, realm); + strcat(buf, "\" ticket"); + auth_abort(ks, buf, r); + + return r; + } + + if (szUserName[0]) // Copy if not there + strcpy (szUserName, cred.pname); +} + +/*+ + * Function: K4 parse authentication reply command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +static int +k4_auth_reply( + kstream ks, + unsigned char *parsedat, + int end_sub) +{ + time_t t; + int x; + char buf[512]; + int i; + des_cblock session_key; + des_key_schedule sched; + static des_cblock challenge; + + if (end_sub < 4) + return KFAILURE; + + if (parsedat[2] != KERBEROS_V4) + return KFAILURE; + + if (parsedat[4] == K4_REJECT) { + buf[0] = 0; + + for (i = 5; i <= end_sub; i++) { + if (parsedat[i] == IAC) + break; + buf[i-5] = parsedat[i]; + buf[i-4] = 0; + } + + if (!buf[0]) + strcpy(buf, "Authentication rejected by remote machine!"); + MessageBox(HWND_DESKTOP, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + if (parsedat[4] == K4_ACCEPT) { + if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) + return KSUCCESS; + + if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) + return KFAILURE; + + des_key_sched(cred.session, sched); + + t = time(NULL); + memcpy(challenge, &t, 4); + memcpy(&challenge[4], &t, 4); + des_ecb_encrypt(&challenge, &session_key, sched, 1); + + /* + * Increment the challenge by 1, and encrypt it for + * later comparison. + */ + for (i = 7; i >= 0; --i) { + x = (unsigned int)challenge[i] + 1; + challenge[i] = x; /* ignore overflow */ + if (x < 256) /* if no overflow, all done */ + break; + } + + des_ecb_encrypt(&challenge, &challenge, sched, 1); + + wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, + KERBEROS_V4, AUTH_CLIENT_TO_SERVER|AUTH_HOW_MUTUAL, K4_CHALLENGE); + memcpy(&buf[7], session_key, 8); + wsprintf(&buf[15], "%c%c", IAC, SE); + TelnetSend(ks, (LPSTR)buf, 17, 0); + + return KSUCCESS; + } + + if (parsedat[4] == K4_RESPONSE) { + if (end_sub < 12) + return KFAILURE; + + if (memcmp(&parsedat[5], challenge, sizeof(challenge)) != 0) { + MessageBox(HWND_DESKTOP, "Remote machine is being impersonated!", + NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + return KSUCCESS; + } + + return KFAILURE; + +} /* auth_reply */ + +#endif /* KRB4 */ +/*++*/ #ifdef KRB5 /* ** +** K5_auth_send - gets authentication bits we need to send to KDC. +** ** Code lifted from telnet sample code in the appl directory. +** +** Result is left in auth +** +** Returns: 0 on failure, 1 on success ** */ -krb5_auth_context *auth_context; -krb5_flags krb5_kdc_default_options = KDC_OPT_RENEWABLE_OK; - -/* 0 on failure, 1 on success */ -int -kerberos5_send (int how) +static int +k5_auth_send (int how) { krb5_error_code r; krb5_ccache ccache; @@ -545,7 +593,7 @@ kerberos5_send (int how) } - if (r = krb5_get_credentials(k5_context, krb5_kdc_default_options, + if (r = krb5_get_credentials(k5_context, KDC_OPT_RENEWABLE_OK, ccache, &cred, &new_cred)) { com_err (NULL, r, "while authorizing."); krb5_free_cred_contents(k5_context, &cred); @@ -569,9 +617,16 @@ kerberos5_send (int how) return(1); } -/*+*/ -int -kerberos5_reply (int how, unsigned char *data, int cnt) { + +/*+ +** +** K5_auth_reply -- checks the reply for mutual authentication. +** +** Code lifted from telnet sample code in the appl directory. +** +*/ +static int +k5_auth_reply (int how, unsigned char *data, int cnt) { static int mutual_complete = 0; data += 4; /* Point to status byte */ @@ -620,7 +675,7 @@ kerberos5_reply (int how, unsigned char *data, int cnt) { return KSUCCESS; default: - return KSUCCESS; // Unknown code + return KSUCCESS; // Unknown reply type } } #endif /* KRB5 */ |