summaryrefslogtreecommitdiffstats
path: root/src/windows/wintel/auth.c
diff options
context:
space:
mode:
authorRichard Basch <probe@mit.edu>1997-02-06 02:31:41 +0000
committerRichard Basch <probe@mit.edu>1997-02-06 02:31:41 +0000
commita0b9ce4bee60136363cfff7a93c4e42eab972c02 (patch)
tree400984337fe3766653ff4cc2cb6b7d3d7f87f3f4 /src/windows/wintel/auth.c
parenta9266b1dec31de9f33b0d032b885edd377a23ee5 (diff)
downloadkrb5-a0b9ce4bee60136363cfff7a93c4e42eab972c02.tar.gz
krb5-a0b9ce4bee60136363cfff7a93c4e42eab972c02.tar.xz
krb5-a0b9ce4bee60136363cfff7a93c4e42eab972c02.zip
Windows/NT integration (V1_0_WIN32_BRANCH merge)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@9788 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/wintel/auth.c')
-rw-r--r--src/windows/wintel/auth.c1128
1 files changed, 652 insertions, 476 deletions
diff --git a/src/windows/wintel/auth.c b/src/windows/wintel/auth.c
index 4d3d380e5..bba43865f 100644
--- a/src/windows/wintel/auth.c
+++ b/src/windows/wintel/auth.c
@@ -3,169 +3,197 @@
*/
#ifdef KRB4
- #include <windows.h>
- #include <time.h>
- #include <string.h>
- #include "winsock.h"
- #include "kerberos.h"
+#include <windows.h>
+#include <time.h>
+#include <string.h>
+#include "winsock.h"
+#include "kerberos.h"
#endif
#ifdef KRB5
- #include <time.h>
- #include <string.h>
- #include "krb5.h"
- #include "com_err.h"
+#include <time.h>
+#include <string.h>
+#include "krb5.h"
+#include "com_err.h"
#endif
#include "telnet.h"
-#include "telopts.h"
+#include "telnet_arpa.h"
+
+#ifdef ENCRYPTION
+#include "encrypt.h"
+#endif
/*
* Constants
*/
- #define IS 0
- #define SEND 1
- #define REPLY 2
- #define NAME 3
-
- #define AUTH_NULL 0
- #define KERBEROS_V4 1
- #define KERBEROS_V5 2
- #define SPX 3
- #define RSA 6
- #define LOKI 10
-
- #define AUTH 0
- #define K4_REJECT 1
- #define K4_ACCEPT 2
- #define K4_CHALLENGE 3
- #define K4_RESPONSE 4
-
- #define K5_REJECT 1
- #define K5_ACCEPT 2
- #define K5_RESPONSE 3 // They had to make it different
-
- #define AUTH_WHO_MASK 1
- #define AUTH_CLIENT_TO_SERVER 0
- #define AUTH_SERVER_TO_CLIENT 1
-
- #define AUTH_HOW_MASK 2
- #define AUTH_HOW_ONE_WAY 0
- #define AUTH_HOW_MUTUAL 2
-
- #ifndef KSUCCESS // Let K5 use K4 constants
- #define KSUCCESS 0
- #define KFAILURE 255
- #endif
+#ifdef KRB4
+#define KRB_AUTH 0
+#define KRB_REJECT 1
+#define KRB_ACCEPT 2
+#define KRB_CHALLENGE 3
+#define KRB_RESPONSE 4
+#endif
+#ifdef KRB5
+#define KRB_AUTH 0 /* Authentication data follows */
+#define KRB_REJECT 1 /* Rejected (reason might follow) */
+#define KRB_ACCEPT 2 /* Accepted */
+#define KRB_RESPONSE 3 /* Response for mutual auth. */
+
+#define KRB_FORWARD 4 /* Forwarded credentials follow */
+#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
+#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
+#endif
+
+#ifndef KSUCCESS /* Let K5 use K4 constants */
+#define KSUCCESS 0
+#define KFAILURE 255
+#endif
+
/*
* Globals
*/
- #ifdef KRB4
- static CREDENTIALS cred;
- static KTEXT_ST auth;
+#ifdef KRB4
+static CREDENTIALS cred;
+static KTEXT_ST auth;
- #define KRB_SERVICE_NAME "rcmd"
- #define KERBEROS_VERSION KERBEROS_V4
+#define KRB_SERVICE_NAME "rcmd"
+#define KERBEROS_VERSION KERBEROS_V4
- static int auth_how;
- static int k4_auth_send (kstream ks);
- static int k4_auth_reply (kstream ks, unsigned char *data, int cnt);
- #endif
- #ifdef KRB5
- static krb5_data auth;
- static int auth_how;
- static krb5_auth_context auth_context;
+static int auth_how;
+static int k4_auth_send(kstream);
+static int k4_auth_reply(kstream, unsigned char *, int);
+#endif
- #define KRB_SERVICE_NAME "host"
- #define KERBEROS_VERSION KERBEROS_V5
+#ifdef KRB5
+static krb5_data auth;
+static int auth_how;
+static krb5_auth_context auth_context;
+krb5_keyblock *session_key = NULL;
+#ifdef FORWARD
+void kerberos5_forward(kstream);
+#endif
- static int k5_auth_send (int how);
- static int k5_auth_reply (int how, unsigned char *data, int cnt);
- #endif
+#define KRB_SERVICE_NAME "host"
+#define KERBEROS_VERSION AUTHTYPE_KERBEROS_V5
+
+static int k5_auth_send(kstream, int);
+static int k5_auth_reply(kstream, int, unsigned char *, int);
+#endif
+
+static int Data(kstream, int, void *, int);
+
+#ifdef ENCRYPTION
+BOOL encrypt_flag = 1;
+#endif
+#ifdef FORWARD
+BOOL forward_flag = 1; /* forward tickets? */
+BOOL forwardable_flag = 1; /* get forwardable tickets to forward? */
+BOOL forwarded_tickets = 0; /* were tickets forwarded? */
+#endif
- BOOL encrypt_enable;
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KERBEROS_V5, };
-/*+
+static int
+Data(kstream ks, int type, void *d, int c)
+{
+ unsigned char *p = str_data + 4;
+ unsigned char *cd = (unsigned char *)d;
+
+ if (c == -1)
+ c = strlen((char *)cd);
+
+ *p++ = AUTHTYPE_KERBEROS_V5;
+ *p = AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL;
+#ifdef ENCRYPTION
+ *p |= AUTH_ENCRYPT_ON;
+#endif
+ p++;
+ *p++ = type;
+ while (c-- > 0) {
+ if ((*p++ = *cd++) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+
+ return(TelnetSend(ks, (LPSTR)str_data, p - str_data, 0));
+}
+
+#ifdef ENCRYPTION
+/*
* Function: Enable or disable the encryption process.
*
* Parameters:
* enable - TRUE to enable, FALSE to disable.
*/
static void
-auth_encrypt_enable(
- BOOL enable)
+auth_encrypt_enable(BOOL enable)
{
- encrypt_enable = enable;
-
-} /* auth_encrypt_enable */
-
+ encrypt_flag = enable;
+}
+#endif
-/*+
+/*
* Function: Abort the authentication process
*
* Parameters:
* ks - kstream to send abort message to.
*/
static void
-auth_abort(
- kstream ks,
- char *errmsg,
- long r)
+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);
- TelnetSend(ks, (LPSTR)buf, 8, 0);
-
- if (errmsg != NULL) {
- strcpy(strTmp, errmsg);
-
- if (r != KSUCCESS) {
- strcat(strTmp, "\n");
- #ifdef KRB4
- lstrcat(strTmp, krb_get_err_text((int) r));
- #endif
- #ifdef KRB5
- lstrcat (strTmp, error_message(r));
- #endif
- }
-
- MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!",
- MB_OK | MB_ICONEXCLAMATION);
- }
-
-} /* auth_abort */
+ char buf[9];
+
+ wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_IS, AUTHTYPE_NULL,
+ AUTHTYPE_NULL, IAC, SE);
+ TelnetSend(ks, (LPSTR)buf, 8, 0);
+
+ if (errmsg != NULL) {
+ strcpy(strTmp, errmsg);
+
+ if (r != KSUCCESS) {
+ strcat(strTmp, "\n");
+#ifdef KRB4
+ lstrcat(strTmp, krb_get_err_text((int)r));
+#endif
+#ifdef KRB5
+ lstrcat(strTmp, error_message(r));
+#endif
+ }
+
+ MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!",
+ MB_OK | MB_ICONEXCLAMATION);
+ }
+}
-/*+
+/*
* Function: Copy data to buffer, doubling IAC character if present.
*
* Parameters:
* kstream - kstream to send abort message to.
*/
static int
-copy_for_net(
- unsigned char *to,
- unsigned char *from,
- int c)
+copy_for_net(unsigned char *to, unsigned char *from, int c)
{
- int n;
-
- n = c;
+ int n;
- while (c-- > 0) {
- if ((*to++ = *from++) == IAC) {
- n++;
- *to++ = IAC;
- }
- }
+ n = c;
- return n;
+ while (c-- > 0) {
+ if ((*to++ = *from++) == IAC) {
+ n++;
+ *to++ = IAC;
+ }
+ }
-} /* copy_for_net */
+ return n;
+}
-/*++
+/*
* Function: Parse authentication send command
*
* Parameters:
@@ -179,70 +207,66 @@ copy_for_net(
* Returns: Kerberos error code.
*/
static int
-auth_send(
- kstream ks,
- unsigned char *parsedat,
- int end_sub)
+auth_send(kstream ks, unsigned char *parsedat, int end_sub)
{
- char buf[512];
- char *pname;
- int plen;
- int r;
- int i;
-
- auth_how = -1;
-
- for (i = 2; i+1 <= end_sub; i += 2) {
- if (parsedat[i] == KERBEROS_VERSION)
- if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER) {
- auth_how = parsedat[i+1] & AUTH_HOW_MASK;
- break;
- }
- }
-
- if (auth_how == -1) {
- auth_abort(ks, NULL, 0);
- return KFAILURE;
- }
-
- #ifdef KRB4
- r = k4_auth_send (ks);
- #endif /* KRB4 */
-
- #ifdef KRB5
- r = k5_auth_send (auth_how);
- #endif /* KRB5 */
+ char buf[512];
+ char *pname;
+ int plen;
+ int r;
+ int i;
+
+ auth_how = -1;
+
+ for (i = 2; i+1 <= end_sub; i += 2) {
+ if (parsedat[i] == KERBEROS_VERSION)
+ if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) {
+ auth_how = parsedat[i+1] & AUTH_HOW_MASK;
+ break;
+ }
+ }
+
+ if (auth_how == -1) {
+ auth_abort(ks, NULL, 0);
+ return KFAILURE;
+ }
- if (! r)
- return KFAILURE;
+#ifdef KRB4
+ r = k4_auth_send(ks);
+#endif /* KRB4 */
+
+#ifdef KRB5
+ r = k5_auth_send(ks, auth_how);
+#endif /* KRB5 */
- plen = strlen (szUserName); // Set by k#_send if needed
- pname = szUserName;
+ if (!r)
+ return KFAILURE;
- wsprintf(buf, "%c%c%c%c", IAC, SB, AUTHENTICATION, NAME);
- memcpy (&buf[4], pname, plen);
- wsprintf(&buf[plen + 4], "%c%c", IAC, SE);
- TelnetSend(ks, (LPSTR)buf, lstrlen(pname)+6, 0);
+ plen = strlen(szUserName); /* Set by k#_send if needed */
+ pname = szUserName;
- wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS,
- KERBEROS_VERSION, auth_how | AUTH_CLIENT_TO_SERVER, AUTH);
+ wsprintf(buf, "%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME);
+ memcpy(&buf[4], pname, plen);
+ wsprintf(&buf[plen + 4], "%c%c", IAC, SE);
+ TelnetSend(ks, (LPSTR)buf, lstrlen(pname)+6, 0);
- #if KRB4
- auth.length = copy_for_net(&buf[7], auth.dat, auth.length);
- #endif /* KRB4 */
- #if KRB5
- auth.length = copy_for_net(&buf[7], auth.data, auth.length);
- #endif /* KRB5 */
+ wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_IS,
+ KERBEROS_VERSION, auth_how | AUTH_WHO_CLIENT, KRB_AUTH);
- wsprintf(&buf[auth.length+7], "%c%c", IAC, SE);
+#if KRB4
+ auth.length = copy_for_net(&buf[7], auth.dat, auth.length);
+#endif /* KRB4 */
+#if KRB5
+ auth.length = copy_for_net(&buf[7], auth.data, auth.length);
+#endif /* KRB5 */
- TelnetSend(ks, (LPSTR)buf, auth.length+9, 0);
+ wsprintf(&buf[auth.length+7], "%c%c", IAC, SE);
- return KSUCCESS;
+ TelnetSend(ks, (LPSTR)buf, auth.length+9, 0);
-} /* auth_send */
+ return KSUCCESS;
+}
-/*+
+/*
* Function: Parse authentication reply command
*
* Parameters:
@@ -256,25 +280,22 @@ auth_send(
* Returns: Kerberos error code.
*/
static int
-auth_reply(
- kstream ks,
- unsigned char *parsedat,
- int end_sub)
+auth_reply(kstream ks, unsigned char *parsedat, int end_sub)
{
- int n;
+ int n;
- #ifdef KRB4
- n = k4_auth_reply (ks, parsedat, end_sub);
- #endif
+#ifdef KRB4
+ n = k4_auth_reply(ks, parsedat, end_sub);
+#endif
- #ifdef KRB5
- n = k5_auth_reply (auth_how, parsedat, end_sub);
- #endif
+#ifdef KRB5
+ n = k5_auth_reply(ks, auth_how, parsedat, end_sub);
+#endif
- return n;
+ return n;
}
-/*+
+/*
* Function: Parse the athorization sub-options and reply.
*
* Parameters:
@@ -285,21 +306,17 @@ auth_reply(
* end_sub - last charcter position in parsedat.
*/
void
-auth_parse(
- kstream ks,
- unsigned char *parsedat,
- int end_sub)
+auth_parse(kstream ks, unsigned char *parsedat, int end_sub)
{
- if (parsedat[1] == SEND)
- auth_send(ks, parsedat, end_sub);
+ if (parsedat[1] == TELQUAL_SEND)
+ auth_send(ks, parsedat, end_sub);
- if (parsedat[1] == REPLY)
- auth_reply(ks, parsedat, end_sub);
-
-} /* auth_parse */
+ if (parsedat[1] == TELQUAL_REPLY)
+ auth_reply(ks, parsedat, end_sub);
+}
-/*+
+/*
* Function: Initialization routine called kstream encryption system.
*
* Parameters:
@@ -307,17 +324,17 @@ auth_parse(
*
* data - user data.
*/
-int INTERFACE
-auth_init(
- kstream str,
- kstream_ptr data)
+int
+auth_init(kstream str, kstream_ptr data)
{
- return 0;
-
-} /* auth_init */
+#ifdef ENCRYPTION
+ encrypt_init(str, data);
+#endif
+ return 0;
+}
-/*+
+/*
* Function: Destroy routine called kstream encryption system.
*
* Parameters:
@@ -325,14 +342,13 @@ auth_init(
*
* data - user data.
*/
-void INTERFACE
-auth_destroy(
- kstream str)
+void
+auth_destroy(kstream str)
{
-} /* auth_destroy */
+}
-/*+
+/*
* Function: Callback to encrypt a block of characters
*
* Parameters:
@@ -344,22 +360,20 @@ auth_destroy(
*
* Returns: number of characters converted.
*/
-int INTERFACE
-auth_encrypt(
- struct kstream_data_block *out,
- struct kstream_data_block *in,
- kstream str)
+int
+auth_encrypt(struct kstream_data_block *out,
+ struct kstream_data_block *in,
+ kstream str)
{
- out->ptr = in->ptr;
-
- out->length = in->length;
+ out->ptr = in->ptr;
- return(out->length);
+ out->length = in->length;
-} /* auth_encrypt */
+ return(out->length);
+}
-/*+
+/*
* Function: Callback to decrypt a block of characters
*
* Parameters:
@@ -371,81 +385,77 @@ auth_encrypt(
*
* Returns: number of characters converted.
*/
-int INTERFACE
-auth_decrypt(
- struct kstream_data_block *out,
- struct kstream_data_block *in,
- kstream str)
+int
+auth_decrypt(struct kstream_data_block *out,
+ struct kstream_data_block *in,
+ kstream str)
{
- out->ptr = in->ptr;
-
- out->length = in->length;
+ out->ptr = in->ptr;
- return(out->length);
+ out->length = in->length;
-} /* auth_decrypt */
+ return(out->length);
+}
-/*++*/
#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
-*/
+ *
+ * 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 (
- kstream ks)
+k4_auth_send(kstream ks)
{
- int r; // Return value
- char instance[INST_SZ];
- char *realm;
- char buf[256];
+ int r; /* Return value */
+ char instance[INST_SZ];
+ char *realm;
+ char buf[256];
- memset(instance, 0, sizeof(instance));
+ memset(instance, 0, sizeof(instance));
- if (realm = krb_get_phost(szHostName))
- lstrcpy(instance, realm);
+ if (realm = krb_get_phost(szHostName))
+ lstrcpy(instance, realm);
- realm = krb_realmofhost(szHostName);
+ 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;
- }
+ 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);
+ 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 == 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 (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);
+ if (!szUserName[0]) /* Copy if not there */
+ strcpy(szUserName, cred.pname);
- return(1);
+ return(1);
}
-/*+
+/*
* Function: K4 parse authentication reply command
*
* Parameters:
@@ -459,232 +469,398 @@ k4_auth_send (
* Returns: Kerberos error code.
*/
static int
-k4_auth_reply(
- kstream ks,
- unsigned char *parsedat,
- int end_sub)
+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;
+ 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;
- }
+ if (parsedat[2] != KERBEROS_V4)
+ return KFAILURE;
+
+ if (parsedat[4] == KRB_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] == KRB_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, TELOPT_AUTHENTICATION, TELQUAL_IS,
+ KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, KRB_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] == KRB_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;
+ 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
-**
-*/
+ *
+ * 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
+ *
+ */
static int
-k5_auth_send (int how)
+k5_auth_send(kstream ks, int how)
{
- krb5_error_code r;
- krb5_ccache ccache;
- krb5_creds cred;
- krb5_creds * new_cred;
- extern krb5_flags krb5_kdc_default_options;
- krb5_flags ap_opts;
- int len;
-
- if (r = krb5_cc_default(k5_context, &ccache)) {
- com_err (NULL, r, "while authorizing.");
- return(0);
- }
-
- memset((char *)&cred, 0, sizeof(cred));
- if (r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME,
- KRB5_NT_SRV_HST, &cred.server)) {
- com_err (NULL, r, "while authorizing.");
- return(0);
+ krb5_error_code r;
+ krb5_ccache ccache;
+ krb5_creds creds;
+ krb5_creds * new_creds;
+ extern krb5_flags krb5_kdc_default_options;
+ krb5_flags ap_opts;
+ char type_check[2];
+ krb5_data check_data;
+ int len;
+#ifdef ENCRYPTION
+ krb5_keyblock *newkey = 0;
+#endif
+
+ if (r = krb5_cc_default(k5_context, &ccache)) {
+ com_err(NULL, r, "while authorizing.");
+ return(0);
+ }
+
+ memset((char *)&creds, 0, sizeof(creds));
+ if (r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME,
+ KRB5_NT_SRV_HST, &creds.server)) {
+ com_err(NULL, r, "while authorizing.");
+ return(0);
+ }
+
+ if (r = krb5_cc_get_principal(k5_context, ccache, &creds.client)) {
+ com_err(NULL, r, "while authorizing.");
+ krb5_free_cred_contents(k5_context, &creds);
+ return(0);
+ }
+ if (szUserName[0] == '\0') { /* Get user name now */
+ len = krb5_princ_component(k5_context, creds.client, 0)->length;
+ memcpy(szUserName,
+ krb5_princ_component(k5_context, creds.client, 0)->data,
+ len);
+ szUserName[len] = '\0';
+ }
+
+ if (r = krb5_get_credentials(k5_context, 0,
+ ccache, &creds, &new_creds)) {
+ com_err(NULL, r, "while authorizing.");
+ krb5_free_cred_contents(k5_context, &creds);
+ return(0);
+ }
+
+ ap_opts = 0;
+ if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ap_opts = AP_OPTS_MUTUAL_REQUIRED;
+
+#ifdef ENCRYPTION
+ ap_opts |= AP_OPTS_USE_SUBKEY;
+#endif
+
+ if (auth_context) {
+ krb5_auth_con_free(k5_context, auth_context);
+ auth_context = 0;
+ }
+ if ((r = krb5_auth_con_init(k5_context, &auth_context))) {
+ com_err(NULL, r, "while initializing auth context");
+ return(0);
+ }
+
+ krb5_auth_con_setflags(k5_context, auth_context,
+ KRB5_AUTH_CONTEXT_RET_TIME);
+
+ type_check[0] = AUTHTYPE_KERBEROS_V5;
+ type_check[1] = AUTH_WHO_CLIENT| (how & AUTH_HOW_MASK);
+#ifdef ENCRYPTION
+ type_check[1] |= AUTH_ENCRYPT_ON;
+#endif
+ check_data.magic = KV5M_DATA;
+ check_data.length = 2;
+ check_data.data = (char *)&type_check;
+
+ r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
+ NULL, new_creds, &auth);
+
+#ifdef ENCRYPTION
+ krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
+ if (session_key) {
+ krb5_free_keyblock(k5_context, session_key);
+ session_key = 0;
+ }
+
+ if (newkey) {
+ /*
+ * keep the key in our private storage, but don't use it
+ * yet---see kerberos5_reply() below
+ */
+ if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) &&
+ (newkey-> enctype != ENCTYPE_DES_CBC_MD5)) {
+ if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
+ (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
+ /* use the session key in credentials instead */
+ krb5_copy_keyblock(k5_context, &new_creds->keyblock, &session_key);
+ else
+ ; /* What goes here? XXX */
+ } else {
+ krb5_copy_keyblock(k5_context, newkey, &session_key);
}
+ krb5_free_keyblock(k5_context, newkey);
+ }
+#endif /* ENCRYPTION */
+
+ krb5_free_cred_contents(k5_context, &creds);
+ krb5_free_creds(k5_context, new_creds);
+
+ if (r) {
+ com_err(NULL, r, "while authorizing.");
+ return(0);
+ }
+
+ return(1);
+}
- if (r = krb5_cc_get_principal(k5_context, ccache, &cred.client)) {
- com_err (NULL, r, "while authorizing.");
- krb5_free_cred_contents(k5_context, &cred);
- return(0);
- }
- if (szUserName[0] == '\0') { /* Get user name now */
- len = krb5_princ_component(k5_context, cred.client, 0)->length;
- memcpy (szUserName,
- krb5_princ_component(k5_context, cred.client, 0)->data,
- len);
- szUserName[len] = '\0';
+/*
+ *
+ * K5_auth_reply -- checks the reply for mutual authentication.
+ *
+ * Code lifted from telnet sample code in the appl directory.
+ *
+ */
+static int
+k5_auth_reply(kstream ks, int how, unsigned char *data, int cnt)
+{
+#ifdef ENCRYPTION
+ Session_Key skey;
+#endif
+ static int mutual_complete = 0;
+
+ data += 4; /* Point to status byte */
+
+ switch (*data++) {
+ case KRB_REJECT:
+ if (cnt > 0) {
+ char *s;
+ wsprintf(strTmp, "Kerberos V5 refuses authentication because\n\t");
+ s = strTmp + strlen(strTmp);
+ strncpy(s, data, cnt);
+ s[cnt] = 0;
+ } else
+ wsprintf(strTmp, "Kerberos V5 refuses authentication");
+ MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION);
+
+ return KFAILURE;
+
+ case KRB_ACCEPT:
+ if (!mutual_complete) {
+ if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
+ wsprintf(strTmp,
+ "Kerberos V5 accepted you, but didn't provide"
+ " mutual authentication");
+ MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION);
+ return KFAILURE;
+ }
+#ifdef ENCRYPTION
+ if (session_key) {
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 0);
+ }
+#endif
}
+#ifdef FORWARD
+ if (forward_flag)
+ kerberos5_forward(ks);
+#endif
- if (r = krb5_get_credentials(k5_context, 0,
- ccache, &cred, &new_cred)) {
- com_err (NULL, r, "while authorizing.");
- krb5_free_cred_contents(k5_context, &cred);
- return(0);
- }
+ return KSUCCESS;
+ break;
- ap_opts = 0;
- if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
- ap_opts = AP_OPTS_MUTUAL_REQUIRED;
+ case KRB_RESPONSE:
+ if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ /* the rest of the reply should contain a krb_ap_rep */
+ krb5_ap_rep_enc_part *reply;
+ krb5_data inbuf;
+ krb5_error_code r;
- r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
- NULL, new_cred, &auth);
+ inbuf.length = cnt;
+ inbuf.data = (char *)data;
- krb5_free_cred_contents(k5_context, &cred);
- krb5_free_creds(k5_context, new_cred);
+ if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
+ com_err(NULL, r, "while authorizing.");
+ return KFAILURE;
+ }
+ krb5_free_ap_rep_enc_part(k5_context, reply);
+
+#ifdef ENCRYPTION
+ if (encrypt_flag && session_key) {
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 0);
+ }
+#endif
+ mutual_complete = 1;
+ }
+ return KSUCCESS;
+
+#ifdef FORWARD
+ case KRB_FORWARD_ACCEPT:
+ forwarded_tickets = 1;
+ return KSUCCESS;
+
+ case KRB_FORWARD_REJECT:
+ forwarded_tickets = 0;
+ if (cnt > 0) {
+ char *s;
+
+ wsprintf(strTmp,
+ "Kerberos V5 refuses forwarded credentials because\n\t");
+ s = strTmp + strlen(strTmp);
+ strncpy(s, data, cnt);
+ s[cnt] = 0;
+ } else
+ wsprintf(strTmp, "Kerberos V5 refuses forwarded credentials");
+
+ MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION);
+ return KFAILURE;
+#endif /* FORWARD */
+
+ default:
+ return KFAILURE; /* Unknown reply type */
+ }
+}
- if (r) {
- com_err (NULL, r, "while authorizing.");
- return(0);
- }
+#ifdef FORWARD
+void
+kerberos5_forward(kstream ks)
+{
+ krb5_error_code r;
+ krb5_ccache ccache;
+ krb5_principal client = 0;
+ krb5_principal server = 0;
+ krb5_data forw_creds;
- return(1);
-}
+ forw_creds.data = 0;
-/*+
-**
-** 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 */
-
- switch (*data++) {
- case K5_REJECT:
- if (cnt > 0)
- wsprintf (strTmp,
- "Kerberos V5 refuses authentication because %.*s",
- cnt, data);
- else
- wsprintf (strTmp, "Kerberos V5 refuses authentication");
- MessageBox (HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION);
-
- return KFAILURE;
-
- case K5_ACCEPT:
- if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
- wsprintf(strTmp, "Kerberos V5 accepted you, "
- "but didn't provide mutual authentication");
- MessageBox (HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION);
- return KSUCCESS;
- }
-
- return KSUCCESS;
- break;
-
- case K5_RESPONSE:
- if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
- /* the rest of the reply should contain a krb_ap_rep */
- krb5_ap_rep_enc_part *reply;
- krb5_data inbuf;
- krb5_error_code r;
-
- inbuf.length = cnt;
- inbuf.data = (char *)data;
-
- if (r = krb5_rd_rep (k5_context, auth_context, &inbuf, &reply)) {
- com_err (NULL, r, "while authorizing.");
- return KFAILURE;
- }
- krb5_free_ap_rep_enc_part(k5_context, reply);
-
- mutual_complete = 1;
- }
- return KSUCCESS;
-
- default:
- return KSUCCESS; // Unknown reply type
- }
+ if ((r = krb5_cc_default(k5_context, &ccache))) {
+ com_err(NULL, r, "Kerberos V5: could not get default ccache");
+ return;
+ }
+
+ if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
+ com_err(NULL, r, "Kerberos V5: could not get default principal");
+ goto cleanup;
+ }
+
+ if ((r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME,
+ KRB5_NT_SRV_HST, &server))) {
+ com_err(NULL, r, "Kerberos V5: could not make server principal");
+ goto cleanup;
+ }
+
+ if ((r = krb5_auth_con_genaddrs(k5_context, auth_context, ks->fd,
+ KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) {
+ com_err(NULL, r, "Kerberos V5: could not gen local full address");
+ goto cleanup;
+ }
+
+ if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client, server,
+ ccache, forwardable_flag, &forw_creds)) {
+ com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
+ goto cleanup;
+ }
+
+ /* Send forwarded credentials */
+ if (!Data(ks, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
+ MessageBox(HWND_DESKTOP,
+ "Not enough room for authentication data", "",
+ MB_OK | MB_ICONEXCLAMATION);
+ }
+
+cleanup:
+ if (client)
+ krb5_free_principal(k5_context, client);
+ if (server)
+ krb5_free_principal(k5_context, server);
+#if 0 /* XXX */
+ if (forw_creds.data)
+ free(forw_creds.data);
+#endif
+ krb5_cc_close(k5_context, ccache);
}
+#endif /* FORWARD */
+
#endif /* KRB5 */