BSD 4_3_Reno development
[unix-history] / usr / src / kerberosIV / krb / rd_priv.c
CommitLineData
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
23static 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
42extern char *errmsg();
43extern int errno;
44extern int krb_debug;
45
46/* static storage */
47
48static u_long c_length;
49static int swap_bytes;
50static struct timeval local_time;
51static long delta_t;
52int 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
83long 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}