Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / kadmin / kadm_ser_wrap.c
1 /* 
2   Copyright (C) 1989 by the Massachusetts Institute of Technology
3
4    Export of this software from the United States of America is assumed
5    to require a specific license from the United States Government.
6    It is the responsibility of any person or organization contemplating
7    export to obtain such a license before exporting.
8
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission.  M.I.T. makes no representations about the suitability of
17 this software for any purpose.  It is provided "as is" without express
18 or implied warranty.
19
20   */
21
22 /*
23  * Kerberos administration server-side support functions
24  */
25
26 /* 
27 kadm_ser_wrap.c
28 unwraps wrapped packets and calls the appropriate server subroutine
29 */
30
31 #include "kadm_locl.h"
32
33 RCSID("$Id: kadm_ser_wrap.c,v 1.25 1999/09/16 20:41:41 assar Exp $");
34
35 /* GLOBAL */
36 Kadm_Server server_parm;
37
38 /* 
39 kadm_ser_init
40 set up the server_parm structure
41 */
42 int
43 kadm_ser_init(int inter,        /* interactive or from file */
44               char *realm,
45               struct in_addr addr)
46 {
47   struct hostent *hp;
48   char hostname[MaxHostNameLen];
49
50   init_kadm_err_tbl();
51   init_krb_err_tbl();
52   if (gethostname(hostname, sizeof(hostname)))
53       return KADM_NO_HOSTNAME;
54
55   strlcpy(server_parm.sname,
56                   PWSERV_NAME,
57                   sizeof(server_parm.sname));
58   strlcpy(server_parm.sinst,
59                   KRB_MASTER,
60                   sizeof(server_parm.sinst));
61   strlcpy(server_parm.krbrlm,
62                   realm,
63                   sizeof(server_parm.krbrlm));
64
65   server_parm.admin_fd = -1;
66   /* setting up the addrs */
67   memset(&server_parm.admin_addr,0, sizeof(server_parm.admin_addr));
68
69   server_parm.admin_addr.sin_port = k_getportbyname (KADM_SNAME,
70                                                      "tcp",
71                                                      htons(751));
72   server_parm.admin_addr.sin_family = AF_INET;
73   if ((hp = gethostbyname(hostname)) == NULL)
74       return KADM_NO_HOSTNAME;
75   server_parm.admin_addr.sin_addr = addr;
76                                 /* setting up the database */
77   if (kdb_get_master_key((inter==1), &server_parm.master_key,
78                          server_parm.master_key_schedule) != 0)
79     return KADM_NO_MAST;
80   if ((server_parm.master_key_version =
81        kdb_verify_master_key(&server_parm.master_key,
82                              server_parm.master_key_schedule,stderr))<0)
83       return KADM_NO_VERI;
84   return KADM_SUCCESS;
85 }
86
87 /*
88  *
89  */
90
91 static void
92 errpkt(u_char *errdat, u_char **dat, int *dat_len, int code)
93 {
94     free(*dat);                 /* free up req */
95     *dat_len = KADM_VERSIZE + 4;
96     memcpy(errdat, KADM_ULOSE, KADM_VERSIZE);
97     krb_put_int (code, errdat + KADM_VERSIZE, 4, 4);
98     *dat = errdat;
99 }
100
101 /*
102 kadm_ser_in
103 unwrap the data stored in dat, process, and return it.
104 */
105 int
106 kadm_ser_in(u_char **dat, int *dat_len, u_char *errdat)
107 {
108     u_char *in_st;                      /* pointer into the sent packet */
109     int in_len,retc;                    /* where in packet we are, for
110                                            returns */
111     u_int32_t r_len;                    /* length of the actual packet */
112     KTEXT_ST authent;                   /* the authenticator */
113     AUTH_DAT ad;                        /* who is this, klink */
114     u_int32_t ncksum;                   /* checksum of encrypted data */
115     des_key_schedule sess_sched;        /* our schedule */
116     MSG_DAT msg_st;
117     u_char *retdat, *tmpdat;
118     int retval, retlen;
119
120     if (*dat_len < (KADM_VERSIZE + sizeof(u_int32_t))
121         || strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE) != 0) {
122         errpkt(errdat, dat, dat_len, KADM_BAD_VER);
123         return KADM_BAD_VER;
124     }
125     in_len = KADM_VERSIZE;
126     /* get the length */
127     if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0 ||
128         (r_len > *dat_len - KADM_VERSIZE - sizeof(u_int32_t))) {
129         errpkt(errdat, dat, dat_len, KADM_LENGTH_ERROR);
130         return KADM_LENGTH_ERROR;
131     }
132     
133     in_len += retc;
134     authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_int32_t);
135     if (authent.length > MAX_KTXT_LEN) {
136         errpkt(errdat, dat, dat_len, KADM_LENGTH_ERROR);
137         return KADM_LENGTH_ERROR;
138     }
139     memcpy(authent.dat, (char *)(*dat) + in_len, authent.length);
140     authent.mbz = 0;
141     /* service key should be set before here */
142     if ((retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst,
143                           server_parm.recv_addr.sin_addr.s_addr, &ad, NULL)))
144     {
145         errpkt(errdat, dat, dat_len, retc + krb_err_base);
146         return retc + krb_err_base;
147     }
148
149 #define clr_cli_secrets() {memset(sess_sched, 0, sizeof(sess_sched)); memset(ad.session, 0,sizeof(ad.session));}
150
151     in_st = *dat + *dat_len - r_len;
152 #ifdef NOENCRYPTION
153     ncksum = 0;
154 #else
155     ncksum = des_quad_cksum((des_cblock *)in_st, (des_cblock *)0, (long) r_len, 0, &ad.session);
156 #endif
157     if (ncksum!=ad.checksum) {          /* yow, are we correct yet */
158         clr_cli_secrets();
159         errpkt(errdat, dat, dat_len, KADM_BAD_CHK);
160         return KADM_BAD_CHK;
161     }
162 #ifdef NOENCRYPTION
163     memset(sess_sched, 0, sizeof(sess_sched));
164 #else
165     des_key_sched(&ad.session, sess_sched);
166 #endif
167     if ((retc = (int) krb_rd_priv(in_st, r_len, sess_sched, &ad.session, 
168                                  &server_parm.recv_addr,
169                                  &server_parm.admin_addr, &msg_st))) {
170         clr_cli_secrets();
171         errpkt(errdat, dat, dat_len, retc + krb_err_base);
172         return retc + krb_err_base;
173     }
174     switch (msg_st.app_data[0]) {
175     case CHANGE_PW:
176         retval = kadm_ser_cpw(msg_st.app_data+1,(int) msg_st.app_length - 1,
177                               &ad, &retdat, &retlen);
178         break;
179     case ADD_ENT:
180         retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length - 1,
181                               &ad, &retdat, &retlen);
182         break;
183     case GET_ENT:
184         retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length - 1,
185                               &ad, &retdat, &retlen);
186         break;
187     case MOD_ENT:
188         retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length - 1,
189                               &ad, &retdat, &retlen);
190         break;
191     case DEL_ENT:
192         retval = kadm_ser_delete(msg_st.app_data + 1, msg_st.app_length - 1, 
193                                  &ad, &retdat, &retlen);
194         break;
195     default:
196         clr_cli_secrets();
197         errpkt(errdat, dat, dat_len, KADM_NO_OPCODE);
198         return KADM_NO_OPCODE;
199     }
200     /* Now seal the response back into a priv msg */
201     tmpdat = (u_char *) malloc(retlen + KADM_VERSIZE + 4);
202     if (tmpdat == NULL) {
203         clr_cli_secrets();
204         errpkt(errdat, dat, dat_len, KADM_NOMEM);
205         return KADM_NOMEM;
206     }
207     free(*dat);
208     memcpy(tmpdat, KADM_VERSTR, KADM_VERSIZE);
209     krb_put_int(retval, tmpdat + KADM_VERSIZE, 4, 4);
210     if (retlen) {
211         memcpy(tmpdat + KADM_VERSIZE + 4, retdat, retlen);
212         free(retdat);
213     }
214     /* slop for mk_priv stuff */
215     *dat = (u_char *) malloc(retlen + KADM_VERSIZE +
216                              sizeof(u_int32_t) + 200);
217     if (*dat == NULL) {
218         clr_cli_secrets();
219         errpkt(errdat, dat, dat_len, KADM_NOMEM);
220         return KADM_NOMEM;
221     }
222     if ((*dat_len = krb_mk_priv(tmpdat, *dat,
223                                 (u_int32_t) (retlen + KADM_VERSIZE +
224                                           sizeof(u_int32_t)),
225                                 sess_sched,
226                                 &ad.session, &server_parm.admin_addr,
227                                 &server_parm.recv_addr)) < 0) {
228         clr_cli_secrets();
229         errpkt(errdat, dat, dat_len, KADM_NO_ENCRYPT);
230         return KADM_NO_ENCRYPT;
231     }
232     clr_cli_secrets();
233     return KADM_SUCCESS;
234 }