]> andersk Git - openssh.git/blob - auth-krb4.c
- Merged more OpenBSD CVS changes:
[openssh.git] / auth-krb4.c
1 /*
2
3    auth-kerberos.c
4
5    Dug Song <dugsong@UMICH.EDU>
6
7    Kerberos v4 authentication and ticket-passing routines.
8
9    $Id$
10 */
11
12 #include "includes.h"
13 #include "packet.h"
14 #include "xmalloc.h"
15 #include "ssh.h"
16
17 #ifdef KRB4
18 char *ticket = NULL;
19
20 void
21 krb4_cleanup_proc(void *ignore)
22 {
23   debug("krb4_cleanup_proc called");
24   
25   if (ticket) {
26     (void) dest_tkt();
27     xfree(ticket);
28     ticket = NULL;
29   }
30 }
31
32 int krb4_init(uid_t uid)
33 {
34   static int cleanup_registered = 0;
35   char *tkt_root = TKT_ROOT;
36   struct stat st;
37   int fd;
38
39   if (!ticket) {
40     /* Set unique ticket string manually since we're still root. */
41     ticket = xmalloc(MAXPATHLEN);
42 #ifdef AFS
43     if (lstat("/ticket", &st) != -1)
44       tkt_root = "/ticket/";
45 #endif /* AFS */
46     snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
47     (void) krb_set_tkt_string(ticket);
48   }
49   /* Register ticket cleanup in case of fatal error. */
50   if (!cleanup_registered) {
51     fatal_add_cleanup(krb4_cleanup_proc, NULL);
52     cleanup_registered = 1;
53   }
54   /* Try to create our ticket file. */
55   if ((fd = mkstemp(ticket)) != -1) {
56     close(fd);
57     return 1;
58   }
59   /* Ticket file exists - make sure user owns it (just passed ticket). */
60   if (lstat(ticket, &st) != -1) {
61     if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
62       return 1;
63   }
64   /* Failure - cancel cleanup function, leaving bad ticket for inspection. */
65   log("WARNING: bad ticket file %s", ticket);
66   fatal_remove_cleanup(krb4_cleanup_proc, NULL);
67   cleanup_registered = 0;
68   xfree(ticket);
69   ticket = NULL;
70   
71   return 0;
72 }
73
74 int auth_krb4(const char *server_user, KTEXT auth, char **client)
75 {
76   AUTH_DAT adat   = { 0 };
77   KTEXT_ST reply;
78   char instance[INST_SZ];
79   int r, s;
80   u_int cksum;
81   Key_schedule schedule;
82   struct sockaddr_in local, foreign;
83   
84   s = packet_get_connection_in();
85   
86   r = sizeof(local);
87   memset(&local, 0, sizeof(local));
88   if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
89     debug("getsockname failed: %.100s", strerror(errno));
90   r = sizeof(foreign);
91   memset(&foreign, 0, sizeof(foreign));
92   if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0) {
93     debug("getpeername failed: %.100s", strerror(errno));
94     fatal_cleanup();
95   }
96   
97   instance[0] = '*'; instance[1] = 0;
98   
99   /* Get the encrypted request, challenge, and session key. */
100   if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
101     packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
102     return 0;
103   }
104   des_key_sched((des_cblock *)adat.session, schedule);
105   
106   *client = xmalloc(MAX_K_NAME_SZ);
107   (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
108                   *adat.pinst ? "." : "", adat.pinst, adat.prealm);
109
110   /* Check ~/.klogin authorization now. */
111   if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
112     packet_send_debug("Kerberos V4 .klogin authorization failed!");
113     log("Kerberos V4 .klogin authorization failed for %s to account %s",
114         *client, server_user);
115     xfree(*client);
116     return 0;
117   }
118   /* Increment the checksum, and return it encrypted with the session key. */
119   cksum = adat.checksum + 1;
120   cksum = htonl(cksum);
121   
122   /* If we can't successfully encrypt the checksum, we send back an empty
123      message, admitting our failure. */
124   if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
125                        schedule, &adat.session, &local, &foreign)) < 0) {
126     packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
127     reply.dat[0] = 0;
128     reply.length = 0;
129   }
130   else reply.length = r;
131   
132   /* Clear session key. */
133   memset(&adat.session, 0, sizeof(&adat.session));
134   
135   packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
136   packet_put_string((char *) reply.dat, reply.length);
137   packet_send();
138   packet_write_wait();
139   return 1;
140 }
141 #endif /* KRB4 */
142
143 #ifdef AFS
144 int auth_kerberos_tgt(struct passwd *pw, const char *string)
145 {
146   CREDENTIALS creds;
147   
148   if (!radix_to_creds(string, &creds)) {
149     log("Protocol error decoding Kerberos V4 tgt");
150     packet_send_debug("Protocol error decoding Kerberos V4 tgt");
151     goto auth_kerberos_tgt_failure;
152   }
153   if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
154     strlcpy(creds.service, "krbtgt", sizeof creds.service);
155   
156   if (strcmp(creds.service, "krbtgt")) {
157     log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname,
158         creds.pinst[0] ? "." : "", creds.pinst, creds.realm, pw->pw_name);
159     packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s",
160                       creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
161                       creds.realm, pw->pw_name);
162     goto auth_kerberos_tgt_failure;
163   }
164   if (!krb4_init(pw->pw_uid))
165     goto auth_kerberos_tgt_failure;
166
167   if (in_tkt(creds.pname, creds.pinst) != KSUCCESS)
168     goto auth_kerberos_tgt_failure;
169   
170   if (save_credentials(creds.service, creds.instance, creds.realm,
171                        creds.session, creds.lifetime, creds.kvno,
172                        &creds.ticket_st, creds.issue_date) != KSUCCESS) {
173     packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
174     goto auth_kerberos_tgt_failure;
175   }
176   /* Successful authentication, passed all checks. */
177   chown(tkt_string(), pw->pw_uid, pw->pw_gid);
178   
179   packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
180                     creds.service, creds.instance, creds.realm, creds.pname,
181                     creds.pinst[0] ? "." : "", creds.pinst, creds.realm);
182   memset(&creds, 0, sizeof(creds));
183   packet_start(SSH_SMSG_SUCCESS);
184   packet_send();
185   packet_write_wait();
186   return 1;
187   
188  auth_kerberos_tgt_failure:
189   krb4_cleanup_proc(NULL);
190   memset(&creds, 0, sizeof(creds));
191   packet_start(SSH_SMSG_FAILURE);
192   packet_send();
193   packet_write_wait();
194   return 0;
195 }
196
197 int auth_afs_token(struct passwd *pw, const char *token_string)
198 {
199   CREDENTIALS creds;
200   uid_t uid = pw->pw_uid;
201
202   if (!radix_to_creds(token_string, &creds)) {
203     log("Protocol error decoding AFS token");
204     packet_send_debug("Protocol error decoding AFS token");
205     packet_start(SSH_SMSG_FAILURE);
206     packet_send();
207     packet_write_wait();
208     return 0;
209   }
210   if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
211     strlcpy(creds.service, "afs", sizeof creds.service);
212   
213   if (strncmp(creds.pname, "AFS ID ", 7) == 0)
214     uid = atoi(creds.pname + 7);
215   
216   if (kafs_settoken(creds.realm, uid, &creds)) {
217     log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
218         pw->pw_name);
219     packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname,
220                       creds.realm, pw->pw_name);
221     memset(&creds, 0, sizeof(creds));
222     packet_start(SSH_SMSG_FAILURE);
223     packet_send();
224     packet_write_wait();
225     return 0;
226   }
227   packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
228                     creds.realm, creds.pname, creds.realm);
229   memset(&creds, 0, sizeof(creds));
230   packet_start(SSH_SMSG_SUCCESS);
231   packet_send();
232   packet_write_wait();
233   return 1;
234 }
235 #endif /* AFS */
This page took 0.064765 seconds and 5 git commands to generate.