Commit | Line | Data |
---|---|---|
84d84a84 C |
1 | /* |
2 | * $Source: /mit/kerberos/src/lib/krb/RCS/rd_priv.c,v $ | |
3 | * $Author: jtkohl $ | |
4 | * | |
5 | * Copyright 1986, 1987, 1988 by the Massachusetts Institute | |
6 | * of Technology. | |
7 | * | |
8 | * For copying and distribution information, please see the file | |
9 | * <mit-copyright.h>. | |
10 | * | |
11 | * This routine dissects a a Kerberos 'private msg', decrypting it, | |
12 | * checking its integrity, and returning a pointer to the application | |
13 | * data contained and its length. | |
14 | * | |
15 | * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...). If | |
16 | * the return value is RD_AP_TIME, then either the times are too far | |
17 | * out of synch, OR the packet was modified. | |
18 | * | |
19 | * Steve Miller Project Athena MIT/DEC | |
20 | */ | |
21 | ||
22 | #ifndef lint | |
23 | static char *rcsid_rd_priv_c= | |
24 | "$Header: rd_priv.c,v 4.14 89/04/28 11:59:42 jtkohl Exp $"; | |
25 | #endif /* lint */ | |
26 | ||
27 | #include <mit-copyright.h> | |
28 | ||
29 | /* system include files */ | |
30 | #include <stdio.h> | |
31 | #include <errno.h> | |
32 | #include <sys/types.h> | |
33 | #include <netinet/in.h> | |
34 | #include <sys/time.h> | |
35 | ||
36 | /* application include files */ | |
37 | #include <des.h> | |
38 | #include <krb.h> | |
39 | #include <prot.h> | |
40 | #include "lsb_addr_comp.h" | |
41 | ||
42 | extern char *errmsg(); | |
43 | extern int errno; | |
44 | extern int krb_debug; | |
45 | ||
46 | /* static storage */ | |
47 | ||
48 | static u_long c_length; | |
49 | static int swap_bytes; | |
50 | static struct timeval local_time; | |
51 | static long delta_t; | |
52 | int private_msg_ver = KRB_PROT_VERSION; | |
53 | ||
54 | /* | |
55 | #ifdef NOENCRPYTION | |
56 | * krb_rd_priv() checks the integrity of an | |
57 | #else | |
58 | * krb_rd_priv() decrypts and checks the integrity of an | |
59 | #endif | |
60 | * AUTH_MSG_PRIVATE message. Given the message received, "in", | |
61 | * the length of that message, "in_length", the key "schedule" | |
62 | #ifdef NOENCRYPTION | |
63 | * and "key", and the network addresses of the | |
64 | #else | |
65 | * and "key" to decrypt with, and the network addresses of the | |
66 | #endif | |
67 | * "sender" and "receiver" of the message, krb_rd_safe() returns | |
68 | * RD_AP_OK if the message is okay, otherwise some error code. | |
69 | * | |
70 | * The message data retrieved from "in" are returned in the structure | |
71 | #ifdef NOENCRYPTION | |
72 | * "m_data". The pointer to the application data | |
73 | #else | |
74 | * "m_data". The pointer to the decrypted application data | |
75 | #endif | |
76 | * (m_data->app_data) refers back to the appropriate place in "in". | |
77 | * | |
78 | * See the file "mk_priv.c" for the format of the AUTH_MSG_PRIVATE | |
79 | * message. The structure containing the extracted message | |
80 | * information, MSG_DAT, is defined in "krb.h". | |
81 | */ | |
82 | ||
83 | long krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) | |
84 | u_char *in; /* pointer to the msg received */ | |
85 | u_long in_length; /* length of "in" msg */ | |
86 | Key_schedule schedule; /* precomputed key schedule */ | |
87 | C_Block key; /* encryption key for seed and ivec */ | |
88 | struct sockaddr_in *sender; | |
89 | struct sockaddr_in *receiver; | |
90 | MSG_DAT *m_data; /*various input/output data from msg */ | |
91 | { | |
92 | register u_char *p,*q; | |
93 | static u_long src_addr; /* Can't send structs since no | |
94 | * guarantees on size */ | |
95 | ||
96 | if (gettimeofday(&local_time,(struct timezone *)0)) | |
97 | return -1; | |
98 | ||
99 | p = in; /* beginning of message */ | |
100 | swap_bytes = 0; | |
101 | ||
102 | if (*p++ != KRB_PROT_VERSION && *(p-1) != 3) | |
103 | return RD_AP_VERSION; | |
104 | private_msg_ver = *(p-1); | |
105 | if (((*p) & ~1) != AUTH_MSG_PRIVATE) | |
106 | return RD_AP_MSG_TYPE; | |
107 | if ((*p++ & 1) != HOST_BYTE_ORDER) | |
108 | swap_bytes++; | |
109 | ||
110 | /* get cipher length */ | |
111 | bcopy((char *)p,(char *)&c_length,sizeof(c_length)); | |
112 | if (swap_bytes) | |
113 | swap_u_long(c_length); | |
114 | p += sizeof(c_length); | |
115 | /* check for rational length so we don't go comatose */ | |
116 | if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length) | |
117 | return RD_AP_MODIFIED; | |
118 | ||
119 | #ifndef NOENCRYPTION | |
120 | /* | |
121 | * decrypt to obtain length, timestamps, app_data, and checksum | |
122 | * use the session key as an ivec | |
123 | */ | |
124 | #endif | |
125 | ||
126 | q = p; /* mark start of encrypted stuff */ | |
127 | ||
128 | #ifndef NOENCRYPTION | |
129 | /* pcbc decrypt, use key as ivec */ | |
130 | pcbc_encrypt((C_Block *) q,(C_Block *) q, (long) c_length, | |
131 | schedule,key,DECRYPT); | |
132 | #endif | |
133 | ||
134 | /* safely get application data length */ | |
135 | bcopy((char *) p,(char *)&(m_data->app_length), | |
136 | sizeof(m_data->app_length)); | |
137 | if (swap_bytes) | |
138 | swap_u_long(m_data->app_length); | |
139 | p += sizeof(m_data->app_length); /* skip over */ | |
140 | ||
141 | if (m_data->app_length + sizeof(c_length) + sizeof(in_length) + | |
142 | sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) + | |
143 | sizeof(src_addr) + VERSION_SZ + MSG_TYPE_SZ | |
144 | > in_length) | |
145 | return RD_AP_MODIFIED; | |
146 | ||
147 | #ifndef NOENCRYPTION | |
148 | /* we're now at the decrypted application data */ | |
149 | #endif | |
150 | m_data->app_data = p; | |
151 | ||
152 | p += m_data->app_length; | |
153 | ||
154 | /* safely get time_5ms */ | |
155 | bcopy((char *) p, (char *)&(m_data->time_5ms), | |
156 | sizeof(m_data->time_5ms)); | |
157 | /* don't need to swap-- one byte for now */ | |
158 | p += sizeof(m_data->time_5ms); | |
159 | ||
160 | /* safely get src address */ | |
161 | bcopy((char *) p,(char *)&src_addr,sizeof(src_addr)); | |
162 | /* don't swap, net order always */ | |
163 | p += sizeof(src_addr); | |
164 | ||
165 | if (src_addr != (u_long) sender->sin_addr.s_addr) | |
166 | return RD_AP_MODIFIED; | |
167 | ||
168 | /* safely get time_sec */ | |
169 | bcopy((char *) p, (char *)&(m_data->time_sec), | |
170 | sizeof(m_data->time_sec)); | |
171 | if (swap_bytes) swap_u_long(m_data->time_sec); | |
172 | ||
173 | p += sizeof(m_data->time_sec); | |
174 | ||
175 | /* check direction bit is the sign bit */ | |
176 | /* For compatibility with broken old code, compares are done in VAX | |
177 | byte order (LSBFIRST) */ | |
178 | if (lsb_net_ulong_less(sender->sin_addr.s_addr, | |
179 | receiver->sin_addr.s_addr)==-1) | |
180 | /* src < recv */ | |
181 | m_data->time_sec = - m_data->time_sec; | |
182 | else if (lsb_net_ulong_less(sender->sin_addr.s_addr, | |
183 | receiver->sin_addr.s_addr)==0) | |
184 | if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1) | |
185 | /* src < recv */ | |
186 | m_data->time_sec = - m_data->time_sec; | |
187 | /* | |
188 | * all that for one tiny bit! | |
189 | * Heaven help those that talk to themselves. | |
190 | */ | |
191 | ||
192 | /* check the time integrity of the msg */ | |
193 | delta_t = abs((int)((long) local_time.tv_sec | |
194 | - m_data->time_sec)); | |
195 | if (delta_t > CLOCK_SKEW) | |
196 | return RD_AP_TIME; | |
197 | if (krb_debug) | |
198 | printf("\ndelta_t = %d",delta_t); | |
199 | ||
200 | /* | |
201 | * caller must check timestamps for proper order and | |
202 | * replays, since server might have multiple clients | |
203 | * each with its own timestamps and we don't assume | |
204 | * tightly synchronized clocks. | |
205 | */ | |
206 | ||
207 | #ifdef notdef | |
208 | bcopy((char *) p,(char *)&cksum,sizeof(cksum)); | |
209 | if (swap_bytes) swap_u_long(cksum) | |
210 | /* | |
211 | * calculate the checksum of the length, sequence, | |
212 | * and input data, on the sending byte order!! | |
213 | */ | |
214 | calc_cksum = quad_cksum(q,NULL,p-q,0,key); | |
215 | ||
216 | if (krb_debug) | |
217 | printf("\ncalc_cksum = %u, received cksum = %u", | |
218 | calc_cksum, cksum); | |
219 | if (cksum != calc_cksum) | |
220 | return RD_AP_MODIFIED; | |
221 | #endif | |
222 | return RD_AP_OK; /* OK == 0 */ | |
223 | } |