import cyrus-sasl-2.1.23
[cyrus-sasl.git] / mac / krb4_sources / mk_safe.c
1 /*
2  * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska H\9agskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the Kungliga Tekniska
20  *      H\9agskolan and its contributors.
21  * 
22  * 4. Neither the name of the Institute nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  * 
26  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38
39 #include "sasl_mac_krb_locl.h"
40
41 RCSID("$Id: mk_safe.c,v 1.2 2001/12/04 02:06:08 rjs3 Exp $");
42
43 /* application include files */
44 #include "krb-archaeology.h"
45
46
47 /* from rd_safe.c */
48 extern int dqc_type;
49 void fixup_quad_cksum(void*, size_t, des_cblock*, void*, void*, int);
50
51 /*
52  * krb_mk_safe() constructs an AUTH_MSG_SAFE message.  It takes some
53  * user data "in" of "length" bytes and creates a packet in "out"
54  * consisting of the user data, a timestamp, and the sender's network
55  * address, followed by a checksum computed on the above, using the
56  * given "key".  The length of the resulting packet is returned.
57  *
58  * The "out" packet consists of:
59  *
60  * Size                 Variable                Field
61  * ----                 --------                -----
62  *
63  * 1 byte               KRB_PROT_VERSION        protocol version number
64  * 1 byte               AUTH_MSG_SAFE |         message type plus local
65  *                      HOST_BYTE_ORDER         byte order in low bit
66  *
67  * ===================== begin checksum ================================
68  * 
69  * 4 bytes              length                  length of user data
70  * length               in                      user data
71  * 1 byte               msg_time_5ms            timestamp milliseconds
72  * 4 bytes              sender->sin.addr.s_addr sender's IP address
73  *
74  * 4 bytes              msg_time_sec or         timestamp seconds with
75  *                      -msg_time_sec           direction in sign bit
76  *
77  * ======================= end checksum ================================
78  *
79  * 16 bytes             big_cksum               quadratic checksum of
80  *                                              above using "key"
81  */
82
83 int32_t
84 krb_mk_safe(void *in, void *out, u_int32_t length, des_cblock *key, 
85             struct sockaddr_in *sender, struct sockaddr_in *receiver)
86 {
87     unsigned char * p = (unsigned char*)out;
88     struct timeval tv;
89     unsigned char *start;
90     u_int32_t src_addr;
91
92     p += krb_put_int(KRB_PROT_VERSION, p, 1, 1);
93     p += krb_put_int(AUTH_MSG_SAFE, p, 1, 1);
94     
95     start = p;
96
97     p += krb_put_int(length, p, 4, 4);
98
99     memcpy(p, in, length);
100     p += length;
101     
102     krb_kdctimeofday(&tv);
103
104     *p++ = tv.tv_usec/5000; /* 5ms */
105     
106     src_addr = sender->sin_addr.s_addr;
107     p += krb_put_address(src_addr, p, 4);
108
109     p += krb_put_int(lsb_time(tv.tv_sec, sender, receiver), p, 4, 4);
110
111     {
112         /* We are faking big endian mode, so we need to fix the
113          * checksum (that is byte order dependent). We always send a
114          * checksum of the new type, unless we know that we are
115          * talking to an old client (this requires a call to
116          * krb_rd_safe first).  
117          */
118         unsigned char new_checksum[16];
119         unsigned char old_checksum[16];
120         fixup_quad_cksum(start, p - start, key, new_checksum, old_checksum, 0);
121         
122         if((dqc_type == DES_QUAD_GUESS && DES_QUAD_DEFAULT == DES_QUAD_OLD) || 
123            dqc_type == DES_QUAD_OLD)
124             memcpy(p, old_checksum, 16);
125         else
126             memcpy(p, new_checksum, 16);
127     }
128     p += 16;
129
130     return p - (unsigned char*)out;
131 }