source: trunk/athena/bin/rkinit/rkinitd/krb.c @ 2269

Revision 2269, 6.7 KB checked in by qjb, 35 years ago (diff)
Initial revision
Line 
1/*
2 * $Header: /afs/dev.mit.edu/source/repository/athena/bin/rkinit/rkinitd/krb.c,v 1.1 1989-11-12 19:35:48 qjb Exp $
3 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/rkinit/rkinitd/krb.c,v $
4 * $Author: qjb $
5 *
6 * This file contains all of the kerberos part of rkinitd.
7 */
8
9#if !defined(lint) && !defined(SABER)
10static char *rcsid = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/rkinit/rkinitd/krb.c,v 1.1 1989-11-12 19:35:48 qjb Exp $";
11#endif lint || SABER
12
13#include <stdio.h>
14#include <sys/types.h>
15#include <errno.h>
16#include <syslog.h>
17#include <netinet/in.h>
18#include <setjmp.h>
19#include <pwd.h>
20#include <krb.h>
21#include <des.h>
22
23#include <rkinit.h>
24#include <rkinit_private.h>
25#include <rkinit_err.h>
26
27#define FAILURE (!RKINIT_SUCCESS)
28
29extern int errno;
30extern char *sys_errlist[];
31
32static char errbuf[BUFSIZ];
33
34typedef struct {
35    jmp_buf env;
36} rkinitd_intkt_info;
37
38static void this_phost(host, hostlen)
39  char *host;
40  int hostlen;
41{
42    char this_host[MAXHOSTNAMELEN + 1];
43
44    BCLEAR(this_host);
45   
46    if (gethostname(this_host, sizeof(this_host)) < 0) {
47        sprintf(errbuf, "gethostname: %s", sys_errlist[errno]);
48        rkinit_errmsg(errbuf);
49        error();
50        exit(1);
51    }
52
53    strncpy(host, krb_get_phost(this_host), hostlen - 1);
54}
55
56static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
57  char *user;
58  char *instance;
59  char *realm;
60  char *arg;
61  int (*key_proc)();
62  KTEXT *cipp;
63{
64    MSG_DAT msg_data;           /* Message data containing decrypted data */
65    KTEXT_ST auth;              /* Authenticator */
66    AUTH_DAT auth_dat;          /* Authentication data */
67    KTEXT cip = *cipp;
68    MSG_DAT scip;
69    int status = 0;
70    des_cblock key;
71    des_key_schedule sched;
72    char phost[MAXHOSTNAMELEN + 1];
73    struct sockaddr_in caddr;   /* client internet address */
74    struct sockaddr_in saddr;   /* server internet address */
75
76    rkinitd_intkt_info *rii = (rkinitd_intkt_info *)arg;
77
78    u_char enc_data[MAX_KTXT_LEN];
79
80    SBCLEAR(auth);
81    SBCLEAR(auth_dat);
82    SBCLEAR(scip);
83    BCLEAR(enc_data);
84
85    scip.app_data = enc_data;
86
87    /*
88     * Exchange with the client our response from the KDC (ticket encrypted
89     * in user's private key) for the same ticket encrypted in our
90     * (not yet known) session key.
91     */
92
93    rpc_exchange_tkt(cip, &scip);
94
95    /*
96     * Get the authenticator
97     */
98
99    SBCLEAR(auth);
100
101    rpc_getauth(&auth, &caddr, &saddr);
102
103    /*
104     * Decode authenticator and extract session key.  The first zero
105     * means we don't care what host this comes from.  This needs to
106     * be done with euid of root so that /etc/srvtab can be read.
107     */
108
109    BCLEAR(phost);
110    this_phost(phost, sizeof(phost));
111
112    /*
113     * This function has to use longjmp to return to the caller
114     * because the kerberos library routine that calls it doesn't
115     * pay attention to the return value it gives.  That means that
116     * if any of these routines failed, the error returned to the client
117     * would be "password incorrect".
118     */
119
120    if (status = krb_rd_req(&auth, KEY, phost, caddr.sin_addr.s_addr,
121                            &auth_dat, KEYFILE)) {
122        sprintf(errbuf, "krb_rd_req: %s", krb_err_txt[status]);
123        rkinit_errmsg(errbuf);
124        longjmp(rii->env, status);
125    }
126
127    bcopy(auth_dat.session, key, sizeof(key));
128    if (des_key_sched(key, sched)) {
129        sprintf(errbuf, "Error in des_key_sched");
130        rkinit_errmsg(errbuf);
131        longjmp(rii->env, RKINIT_DES);
132    }
133
134    /* Decrypt the data. */
135    if ((status =
136         krb_rd_priv((u_char *)scip.app_data, scip.app_length,
137                     sched, key, &caddr, &saddr, &msg_data)) == KSUCCESS) {
138        cip->length = msg_data.app_length;
139        bcopy(msg_data.app_data, cip->dat, msg_data.app_length);
140        cip->dat[cip->length] = 0;
141    }
142    else {
143        sprintf(errbuf, "krb_rd_priv: %s", krb_err_txt[status]);
144        rkinit_errmsg(errbuf);
145        longjmp(rii->env, status);
146    }
147   
148    return(status);
149}
150
151static int validate_user(aname, inst, realm, username, errmsg)
152  char *aname;
153  char *inst;
154  char *realm;
155  char *username;
156  char *errmsg;
157{
158    struct passwd *pwnam;       /* For access_check and uid */
159    AUTH_DAT auth_dat;
160
161    SBCLEAR(auth_dat);
162
163    if ((pwnam = getpwnam(username)) == NULL) {
164        sprintf(errmsg, "%s does not exist on the remote host.", username);
165        return(FAILURE);
166    }
167
168    strcpy(auth_dat.pname, aname);
169    strcpy(auth_dat.pinst, inst);
170    strcpy(auth_dat.prealm, realm);
171
172    if (kuserok(&auth_dat, username) != KSUCCESS) {
173        sprintf(errmsg, "%s has not allowed you to log in with", username);
174        if (strlen(auth_dat.pinst))
175            sprintf(errmsg, "%s %s.%s", errmsg, auth_dat.pname,
176                    auth_dat.pinst);
177        else
178            sprintf(errmsg, "%s %s", errmsg, auth_dat.pname);
179        sprintf(errmsg, "%s@%s tickets.", errmsg, auth_dat.prealm);
180        return(FAILURE);
181    }
182   
183    /*
184     * Set real uid to owner of ticket file.  The library takes care
185     * of making the appropriate change.
186     */
187    if (setruid(pwnam->pw_uid) < 0) {
188        sprintf(errmsg,
189                "Failure setting ruid to %d: %s\n", sys_errlist[errno]);
190        strcpy(errbuf, errmsg);
191        error();
192        return(FAILURE);
193    }
194       
195    return(RKINIT_SUCCESS);
196}
197
198int get_tickets(version)
199  int version;
200{
201    rkinit_info info;
202    AUTH_DAT auth_dat;
203
204    int status;
205    char errmsg[BUFSIZ];        /* error message for client */
206
207    rkinitd_intkt_info rii;
208
209    SBCLEAR(info);
210    SBCLEAR(auth_dat);
211    BCLEAR(errmsg);
212    SBCLEAR(rii);
213
214    rpc_get_rkinit_info(&info);
215
216    /*
217     * The validate_user routine makes sure that the principal in question
218     * is allowed to log in as username, and if so, does a setuid(localuid).
219     * If there is an access violation or an error in setting the uid,
220     * an error is returned and the string errmsg is initialized with
221     * an error message that will be sent back to the client.
222     */
223    if ((status = validate_user(info.aname, info.inst, info.realm,
224                                info.username, errmsg)) != RKINIT_SUCCESS) {
225        rpc_send_error(errmsg);
226        exit(0);
227    }
228    else
229        rpc_send_success();
230
231    /*
232     * If the name of a ticket file was specified, set it; otherwise,
233     * just use the default.
234     */
235    if (strlen(info.tktfilename))
236        krb_set_tkt_string(info.tktfilename);
237   
238    /*
239     * Call internal kerberos library routine so that we can supply
240     * our own ticket decryption routine.
241     */
242
243    /*
244     * We need a setjmp here because krb_get_in_tkt ignores the
245     * return value of decrypt_tkt.  Thus if we want any of its
246     * return values to reach the client, we have to jump out of
247     * the routine.
248     */
249
250    if (setjmp(rii.env) == 0) {
251        if (status = krb_get_in_tkt(info.aname, info.inst, info.realm,
252                                    info.sname, info.sinst, info.lifetime,
253                                    NULL, decrypt_tkt, (char *)&rii)) {
254            strcpy(errmsg, krb_err_txt[status]);
255            rpc_send_error(errmsg);
256        }
257        else
258            rpc_send_success();
259    }
260    else
261        rpc_send_error(errbuf);
262   
263    return(RKINIT_SUCCESS);
264}
Note: See TracBrowser for help on using the repository browser.