]> arthur.barton.de Git - netatalk.git/blob - etc/uams/uams_krb4/kuam.c
Remove bdb env on exit
[netatalk.git] / etc / uams / uams_krb4 / kuam.c
1 /*
2  * $Id: kuam.c,v 1.4 2001-06-25 20:13:45 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1994 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #ifdef UAM_AFSKRB
13
14 #include <mit-copyright.h>
15 #include <krb.h>
16 #include <des.h>
17 #include <prot.h>
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22
23 /* use the bsd time.h struct defs for PC too! */
24 #include <sys/time.h>
25 #include <sys/types.h>
26
27 int     swap_bytes;
28
29 /*
30  * krb_get_in_tkt() gets a ticket for a given principal to use a given
31  * service and stores the returned ticket and session key for future
32  * use.
33  *
34  * The "user", "instance", and "realm" arguments give the identity of
35  * the client who will use the ticket.  The "service" and "sinstance"
36  * arguments give the identity of the server that the client wishes
37  * to use.  (The realm of the server is the same as the Kerberos server
38  * to whom the request is sent.)  The "life" argument indicates the
39  * desired lifetime of the ticket; the "key_proc" argument is a pointer
40  * to the routine used for getting the client's private key to decrypt
41  * the reply from Kerberos.  The "decrypt_proc" argument is a pointer
42  * to the routine used to decrypt the reply from Kerberos; and "arg"
43  * is an argument to be passed on to the "key_proc" routine.
44  *
45  * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
46  * returns an error code:  If an AUTH_MSG_ERR_REPLY packet is returned
47  * by Kerberos, then the error code it contains is returned.  Other
48  * error codes returned by this routine include INTK_PROT to indicate
49  * wrong protocol version, INTK_BADPW to indicate bad password (if
50  * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
51  * the wrong server or the ticket store couldn't be initialized.
52  *
53  * The format of the message sent to Kerberos is as follows:
54  *
55  * Size                 Variable                Field
56  * ----                 --------                -----
57  *
58  * 1 byte               KRB_PROT_VERSION        protocol version number
59  * 1 byte               AUTH_MSG_KDC_REQUEST |  message type
60  *                      HOST_BYTE_ORDER         local byte order in lsb
61  * string               user                    client's name
62  * string               instance                client's instance
63  * string               realm                   client's realm
64  * 4 bytes              tlocal.tv_sec           timestamp in seconds
65  * 1 byte               life                    desired lifetime
66  * string               service                 service's name
67  * string               sinstance               service's instance
68  */
69
70 kuam_get_in_tkt(user, instance, realm, service, sinstance, life, rpkt )
71     char        *user;
72     char        *instance;
73     char        *realm;
74     char        *service;
75     char        *sinstance;
76     int         life;
77     KTEXT       rpkt;
78 {
79     KTEXT_ST pkt_st;
80     KTEXT pkt = &pkt_st;        /* Packet to KDC */
81     KTEXT_ST cip_st;
82     KTEXT cip = &cip_st;        /* Returned Ciphertext */
83     KTEXT_ST tkt_st;
84     KTEXT tkt = &tkt_st;        /* Current ticket */
85     unsigned char *v = pkt->dat; /* Prot vers no */
86     unsigned char *t = (pkt->dat+1); /* Prot msg type */
87     int msg_byte_order;
88     int kerror;
89     struct timeval t_local;
90     u_int32_t rep_err_code;
91
92
93     /* BUILD REQUEST PACKET */
94
95     /* Set up the fixed part of the packet */
96     *v = (unsigned char) KRB_PROT_VERSION;
97     *t = (unsigned char) AUTH_MSG_KDC_REQUEST;
98     *t |= HOST_BYTE_ORDER;
99
100     /* Now for the variable info */
101     (void) strcpy((char *)(pkt->dat+2),user); /* aname */
102     pkt->length = 3 + strlen(user);
103     (void) strcpy((char *)(pkt->dat+pkt->length),
104                   instance);    /* instance */
105     pkt->length += 1 + strlen(instance);
106     (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */
107     pkt->length += 1 + strlen(realm);
108
109     (void) gettimeofday(&t_local,(struct timezone *) 0);
110     /* timestamp */
111     memcpy((pkt->dat+pkt->length), &(t_local.tv_sec), 4);
112     pkt->length += 4;
113
114     *(pkt->dat+(pkt->length)++) = (char) life;
115     (void) strcpy((char *)(pkt->dat+pkt->length),service);
116     pkt->length += 1 + strlen(service);
117     (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
118     pkt->length += 1 + strlen(sinstance);
119
120     rpkt->length = 0;
121
122     /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
123
124     if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
125
126     /* check packet version of the returned packet */
127     if (pkt_version(rpkt) != KRB_PROT_VERSION)
128         return(INTK_PROT);
129
130     /* Check byte order */
131     msg_byte_order = pkt_msg_type(rpkt) & 1;
132     swap_bytes = 0;
133     if (msg_byte_order != HOST_BYTE_ORDER) {
134         swap_bytes++;
135     }
136
137     switch (pkt_msg_type(rpkt) & ~1) {
138     case AUTH_MSG_KDC_REPLY:
139         break;
140     case AUTH_MSG_ERR_REPLY:
141         memcpy(&rep_err_code,pkt_err_code(rpkt),4);
142         if (swap_bytes) swap_u_long(rep_err_code);
143         return((int)rep_err_code);
144     default:
145         return(INTK_PROT);
146     }
147
148     return( INTK_OK );
149 }
150
151 kuam_set_in_tkt( user, instance, realm, service, sinstance, ptr)
152     char        *user, *instance, *realm, *service, *sinstance, *ptr;
153 {
154     KTEXT_ST            tkt_st;
155     KTEXT               tkt = &tkt_st;
156     struct timeval      t_local;
157     int                 lifetime, kvno, kerror;
158     int32_t             kdc_time;
159     C_Block             ses;
160     char                s_name[ SNAME_SZ ], s_instance[ INST_SZ ];
161     char                rlm[ REALM_SZ ];
162
163     /* extract session key */
164     memcpy(ses, ptr, 8);
165     ptr += 8;
166
167     /* extract server's name */
168     (void) strcpy(s_name,ptr);
169     ptr += strlen(s_name) + 1;
170
171     /* extract server's instance */
172     (void) strcpy(s_instance,ptr);
173     ptr += strlen(s_instance) + 1;
174
175     /* extract server's realm */
176     (void) strcpy(rlm,ptr);
177     ptr += strlen(rlm) + 1;
178
179     /* extract ticket lifetime, server key version, ticket length */
180     /* be sure to avoid sign extension on lifetime! */
181     lifetime = (unsigned char) ptr[0];
182     kvno = (unsigned char) ptr[1];
183     tkt->length = (unsigned char) ptr[2];
184     ptr += 3;
185
186     /* extract ticket itself */
187     memcpy( tkt->dat, ptr, tkt->length);
188     ptr += tkt->length;
189
190     if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
191         strcmp(rlm, realm))     /* not what we asked for */
192         return(INTK_ERR);       /* we need a better code here XXX */
193
194     /* check KDC time stamp */
195     memcpy(&kdc_time, ptr, 4); /* Time (coarse) */
196     if (swap_bytes) swap_u_long(kdc_time);
197
198     ptr += 4;
199
200     (void) gettimeofday(&t_local,(struct timezone *) 0);
201     if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
202         return(RD_AP_TIME);             /* XXX should probably be better
203                                            code */
204     }
205
206     /* initialize ticket cache */
207     if (in_tkt(user,instance) != KSUCCESS)
208         return(INTK_ERR);
209
210     /* stash ticket, session key, etc. for future use */
211     if (kerror = save_credentials(s_name, s_instance, rlm, ses,
212                                   lifetime, kvno, tkt, t_local.tv_sec))
213         return(kerror);
214
215     return(INTK_OK);
216 }
217
218 #endif /* UAM_AFSKRB */