summaryrefslogtreecommitdiff
path: root/security/ssh/patches/patch-bk
blob: b18f6e4eb54801beef98d21c8d5b428436568c62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
$NetBSD: patch-bk,v 1.2 2000/03/20 02:25:57 itojun Exp $

--- sshconnect.c-	Wed May 12 20:19:29 1999
+++ sshconnect.c	Mon Mar 20 09:55:37 2000
@@ -215,7 +215,6 @@
 #include "userfile.h"
 #include "emulate.h"
 
-#ifdef KERBEROS
 #ifdef KRB5
 #include <krb5.h>
 
@@ -223,7 +222,19 @@
 krb5_context ssh_context = 0;
 krb5_auth_context auth_context = 0;
 #endif /* KRB5 */
-#endif /* KERBEROS */
+
+#ifdef KRB4
+#include <krb.h>
+#ifdef AFS
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#include <kafs.h>
+#endif /* AFS */
+#endif /* KRB4 */
 
 /* Session id for the current session. */
 unsigned char session_id[16];
@@ -932,10 +943,9 @@
   return 0;
 }
 
-#ifdef KERBEROS
+#ifdef KRB5
 int try_kerberos_authentication(void)
 {
-#ifdef KRB5
   char *remotehost;
   krb5_data auth;
   krb5_error_code r;
@@ -1084,15 +1094,118 @@
     krb5_free_ap_rep_enc_part(ssh_context, repl);
   
   return(ret_stat);
+}
 #endif /* KRB5 */
+
+#ifdef KRB4
+int try_kerberos_authentication()
+{
+  KTEXT_ST auth;                     /* Kerberos data */
+  char *reply;
+  char inst[INST_SZ];
+  char *realm;
+  char *service;
+  CREDENTIALS cred;
+  int r, type;
+  Key_schedule schedule;
+  u_long checksum, cksum;
+  MSG_DAT msg_data;
+  struct sockaddr_in local, foreign;
+  struct stat st;
+  
+  /* Don't do anything if we don't have any tickets. */
+  if (stat(tkt_string(), &st) < 0) return 0;
+  
+  strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
+  
+  realm = (char *)krb_realmofhost(get_canonical_hostname());
+  if (!realm) {
+    debug("Kerberos V4: no realm for %s", get_canonical_hostname());
+    return 0;
+  }
+  /* This can really be anything. */
+  checksum = (u_long) getpid();
+  
+  if (r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum)) {
+    debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
+    return 0;
+  }
+  /* Get session key to decrypt the server's reply with. */
+  if (r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred)) {
+     debug("get_cred failed: %s", krb_err_txt[r]);
+     return 0;
+  }
+  des_key_sched((des_cblock *)cred.session, schedule);
+  
+  /* Send authentication info to server. */
+  packet_start(SSH_CMSG_AUTH_KERBEROS);
+  packet_put_string((char *)auth.dat, auth.length);
+  packet_send();
+  packet_write_wait();
+  
+  /* zero the buffer */
+  (void) memset(auth.dat, 0, MAX_KTXT_LEN);
+  
+  r = sizeof(local);
+  memset(&local, 0, sizeof(local));
+  if (getsockname(packet_get_connection_in(),
+ 		  (struct sockaddr *) &local, &r) < 0)
+    debug("getsockname failed: %.100s", strerror(errno));
+  
+  r = sizeof(foreign);
+  memset(&foreign, 0, sizeof(foreign));
+   if (getpeername(packet_get_connection_in(),
+		   (struct sockaddr *)&foreign, &r) < 0)
+     debug("getpeername failed: %.100s", strerror(errno));
+   
+   /* Get server reply. */
+   type = packet_read();
+   switch(type) {
+     
+   case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
+     debug("Kerberos V4 authentication failed.");
+     return 0;
+     break;
+     
+   case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
+     debug("Kerberos V4 authentication accepted.");
+     
+     /* Get server's response. */
+     reply = packet_get_string((unsigned int *)&auth.length);
+     memcpy(auth.dat, reply, auth.length);
+     xfree(reply);
+     
+     /* If his response isn't properly encrypted with the session key,
+        and the decrypted checksum fails to match, he's bogus. Bail out. */
+     if (r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
+			 &foreign, &local, &msg_data)) {
+       debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
+       packet_disconnect("Kerberos V4 challenge failed!");
+     }
+     /* fetch the (incremented) checksum that we supplied in the request */
+     (void)memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum));
+     cksum = ntohl(cksum);
+     
+     /* If it matches, we're golden. */
+     if (cksum == checksum + 1) {
+       debug("Kerberos V4 challenge successful.");
+       return 1;
+     }
+     else
+       packet_disconnect("Kerberos V4 challenge failed!");
+     break;
+     
+   default:
+     packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
+   }
 }
-#endif /* KERBEROS */
+#endif /* KRB4 */
+
 
-#ifdef KERBEROS_TGT_PASSING
 /* Forward our local Kerberos tgt to the server. */
+#ifdef KRB5
 int send_kerberos_tgt(void)
 {
-#ifdef KRB5
   char *remotehost;
   krb5_principal client;
   krb5_principal server;
@@ -1172,22 +1285,117 @@
     krb5_free_principal(ssh_context, client);
     krb5_free_principal(ssh_context, server);
     
-    type = packet_read();
-    if (type == SSH_SMSG_SUCCESS)
-      {
-        debug("Kerberos V5 TGT passing was successful.");
-        return 1;
-      }
-    else
-      if (type != SSH_SMSG_FAILURE)
-        packet_disconnect("Protocol error on Kerberos tgt response: %d", type);
-      else 
-        debug("Kerberos V5 TGT passing failed.");
-    
-    return 0;
+    return 1;
+}
 #endif /* KRB5 */
+
+#ifdef AFS
+int send_kerberos_tgt()
+{
+  CREDENTIALS *creds;
+  char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+  int r, type;
+  unsigned char buffer[8192];
+  struct stat st;
+
+  /* Don't do anything if we don't have any tickets. */
+  if (stat(tkt_string(), &st) < 0) return 0;
+      
+  creds = xmalloc(sizeof(CREDENTIALS));
+  
+  if ((r=krb_get_tf_fullname(TKT_FILE,pname,pinst,prealm)) != KSUCCESS) {
+    debug("Kerberos V4 tf_fullname failed: %s",krb_err_txt[r]);
+    return 0;
+  }
+  if ((r=krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
+    debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
+    return 0;
+  }
+  if (time(0) >
+#ifdef HAVE_KRB_LIFE_TO_TIME
+      (unsigned long)krb_life_to_time(creds->issue_date, creds->lifetime)) {
+#else
+      (creds->issue_date + ((unsigned char)creds->lifetime * 5 * 60))) {
+#endif /* HAVE_KRB_LIFE_TO_TIME */
+    debug("Kerberos V4 ticket expired: %s", TKT_FILE);
+    return 0;
+  }
+
+  creds_to_radix(creds, buffer);
+  xfree(creds);
+    
+  packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
+  packet_put_string((char *)buffer, strlen(buffer));
+  packet_send();
+  packet_write_wait();
+
+  return 1;
 }
-#endif /* KERBEROS_TGT_PASSING */
+
+/* Forwards our AFS tokens to the server. */
+void send_afs_tokens(void)
+{
+  CREDENTIALS creds;
+  struct ViceIoctl parms;
+  struct ClearToken ct;
+  int i, type;
+  int len;
+  char buf[2048], *p, *server_cell;
+  unsigned char buffer[8192];
+
+  /* Move over ktc_GetToken, here's something leaner. */
+  for (i = 0; i < 100; i++) { /* just in case */
+    parms.in = (char *)&i;
+    parms.in_size = sizeof(i);
+    parms.out = buf;
+    parms.out_size = sizeof(buf);
+    if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break;
+    p = buf;
+    
+    /* Get secret token. */
+    memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
+    if (creds.ticket_st.length > MAX_KTXT_LEN) break;
+    p += sizeof(unsigned int);
+    memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
+    p += creds.ticket_st.length;
+        
+    /* Get clear token. */
+    memcpy(&len, p, sizeof(len));
+    if (len != sizeof(struct ClearToken)) break;
+    p += sizeof(len);
+    memcpy(&ct, p, len);
+    p += len;
+    p += sizeof(len); /* primary flag */
+    server_cell = p;
+
+    /* Flesh out our credentials. */
+    strcpy(creds.service, "afs");
+    creds.instance[0] = '\0';
+    strncpy(creds.realm, server_cell, REALM_SZ);
+    memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
+    creds.issue_date = ct.BeginTimestamp;
+    creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
+    creds.kvno = ct.AuthHandle;
+    snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
+    creds.pinst[0] = '\0';
+
+    /* Encode token, ship it off. */
+    if (!creds_to_radix(&creds, buffer)) break;
+    packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
+    packet_put_string((char *)buffer, strlen(buffer));
+    packet_send();
+    packet_write_wait();
+
+    /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */
+    type = packet_read();
+
+    if (type == SSH_SMSG_FAILURE)
+      debug("AFS token for cell %s rejected.", server_cell);
+    else if (type != SSH_SMSG_SUCCESS)
+      packet_disconnect("Protocol error on AFS token response: %d", type);
+  }  
+}
+#endif /* AFS */
 
 /* Waits for the server identification string, and sends our own identification
    string. */
@@ -1285,14 +1493,12 @@
   unsigned char check_bytes[8];
   unsigned int supported_ciphers, supported_authentications, protocol_flags;
   HostStatus host_status;
-#ifdef KERBEROS 
 #ifdef KRB5
   char *kuser;
   krb5_ccache ccache;
   krb5_error_code problem;
   krb5_principal client;
-#endif
-#endif
+#endif /* KRB5 */
   
   /* Convert the user-supplied hostname into all lowercase. */
   host = xstrdup(orighost);
@@ -1595,7 +1801,6 @@
 
   debug("Received encrypted confirmation.");
 
-#ifdef KERBEROS 
 #ifdef KRB5
   if (!ssh_context)
     {
@@ -1629,7 +1834,6 @@
         debug("Kerberos V5: could not get default ccache.");
     }
 #endif /* KRB5 */
-#endif /* KERBEROS */
   
   /* Send the name of the user to log in as on the server. */
   packet_start(SSH_CMSG_USER);
@@ -1647,24 +1851,39 @@
     packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
                       type);
 
-#ifdef KERBEROS_TGT_PASSING
+#if defined(KRB5) || defined(AFS)
   /* Try Kerberos tgt passing if the server supports it. */
   if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
       options->kerberos_tgt_passing)
     {
       if (options->cipher == SSH_CIPHER_NONE)
         log_msg("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
-      (void)send_kerberos_tgt();
+      if (send_kerberos_tgt())
+      {
+        type = packet_read();
+        if (type == SSH_SMSG_FAILURE)
+	  debug("Kerberos TGT passing failed.");
+        else if (type != SSH_SMSG_SUCCESS)
+	  packet_disconnect("Protocol error on Kerberos tgt response: %d", type);
+      }
     }
-#endif /* KERBEROS_TGT_PASSING */
+#endif /* KRB5 || AFS */
+
+#ifdef AFS
+  /* Try AFS token passing if the server supports it. */
+  if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
+      options->afs_token_passing && k_hasafs())  {
+    if (options->cipher == SSH_CIPHER_NONE)
+      log_msg("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
+    send_afs_tokens();
+  }
+#endif /* AFS */
   
-#ifdef KERBEROS
-#ifdef KRB5
+#if defined(KRB4) || defined(KRB5)
   if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
       options->kerberos_authentication)
     {
-      debug("Trying Kerberos V5 authentication.");
-#endif
+      debug("Trying Kerberos authentication.");
       if (try_kerberos_authentication()) {
         /* The server should respond with success or failure. */
         type = packet_read();
@@ -1673,10 +1892,8 @@
         if (type != SSH_SMSG_FAILURE)
           packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
       }
-#ifdef KRB5
     }
-#endif
-#endif /* KERBEROS */
+#endif /* KRB4 || KRB5 */
 
   /* Use rhosts authentication if running in privileged socket and we do not
      wish to remain anonymous. */