Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / appl / ftp / ftpd / auth.c
1 /*
2  * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
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ögskolan 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 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 RCSID("$Id: auth.c,v 1.11 1997/05/04 23:09:00 assar Exp $");
42 #endif
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #ifdef HAVE_SYS_TYPES_H
48 #include <sys/types.h>
49 #endif
50 #ifdef HAVE_SYS_SOCKET_H
51 #include <sys/socket.h>
52 #endif
53 #if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
54 #include <sys/ioctl.h>
55 #endif
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59
60 #include "extern.h"
61 #include "krb4.h"
62 #include "auth.h"
63
64 static struct at auth_types [] = {
65     { "KERBEROS_V4", krb4_auth, krb4_adat, krb4_pbsz, krb4_prot, krb4_ccc, 
66       krb4_mic, krb4_conf, krb4_enc, krb4_read, krb4_write, krb4_userok, 
67       krb4_vprintf },
68     { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
69 };
70
71 struct at *ct;
72
73 int data_protection;
74 int buffer_size;
75 unsigned char *data_buffer;
76 int auth_complete;
77
78
79 char *protection_names[] = {
80     "clear", "safe", 
81     "confidential", "private"
82 };
83
84
85 void auth_init(void)
86 {
87 }
88
89 char *ftp_command;
90 int prot_level;
91
92 void new_ftp_command(char *command)
93 {
94     ftp_command = command;
95 }
96
97 void delete_ftp_command(void)
98 {
99     if(ftp_command){
100         free(ftp_command);
101         ftp_command = NULL;
102     }
103 }
104
105 int auth_ok(void)
106 {
107     return ct && auth_complete;
108 }
109
110 void auth(char *auth)
111 {
112     for(ct=auth_types; ct->name; ct++){
113         if(!strcasecmp(auth, ct->name)){
114             ct->auth(auth);
115             return;
116         }
117     }
118     reply(504, "%s is not a known security mechanism", auth);
119 }
120
121 void adat(char *auth)
122 {
123     if(ct && !auth_complete)
124         ct->adat(auth);
125     else
126         reply(503, "You must (re)issue an AUTH first.");
127 }
128
129 void pbsz(int size)
130 {
131     int old = buffer_size;
132     if(auth_ok())
133         ct->pbsz(size);
134     else
135         reply(503, "Incomplete security data exchange.");
136     if(buffer_size != old){
137         if(data_buffer)
138             free(data_buffer);
139         data_buffer = malloc(buffer_size + 4);
140     }
141 }
142
143 void prot(char *pl)
144 {
145     int p = -1;
146
147     if(buffer_size == 0){
148         reply(503, "No protection buffer size negotiated.");
149         return;
150     }
151
152     if(!strcasecmp(pl, "C"))
153         p = prot_clear;
154     
155     if(!strcasecmp(pl, "S"))
156         p = prot_safe;
157     
158     if(!strcasecmp(pl, "E"))
159         p = prot_confidential;
160     
161     if(!strcasecmp(pl, "P"))
162         p = prot_private;
163     
164     if(p == -1){
165         reply(504, "Unrecognized protection level.");
166         return;
167     }
168     
169     if(auth_ok()){
170         if(ct->prot(p)){
171             reply(536, "%s does not support %s protection.", 
172                   ct->name, protection_names[p]);
173         }else{
174             data_protection = p;
175             reply(200, "Data protection is %s.", 
176                   protection_names[data_protection]);
177         }
178     }else{
179         reply(503, "Incomplete security data exchange.");
180     }
181 }
182
183 void ccc(void)
184 {
185     if(auth_ok()){
186         if(!ct->ccc())
187             prot_level = prot_clear;
188     }else
189         reply(503, "Incomplete security data exchange.");
190 }
191
192 void mic(char *msg)
193 {
194     if(auth_ok()){
195         if(!ct->mic(msg))
196             prot_level = prot_safe;
197     }else
198         reply(503, "Incomplete security data exchange.");
199 }
200
201 void conf(char *msg)
202 {
203     if(auth_ok()){
204         if(!ct->conf(msg))
205             prot_level = prot_confidential;
206     }else
207         reply(503, "Incomplete security data exchange.");
208 }
209
210 void enc(char *msg)
211 {
212     if(auth_ok()){
213         if(!ct->enc(msg))
214             prot_level = prot_private;
215     }else
216         reply(503, "Incomplete security data exchange.");
217 }
218
219 int auth_read(int fd, void *data, int length)
220 {
221     if(auth_ok() && data_protection)
222         return ct->read(fd, data, length);
223     else
224         return read(fd, data, length);
225 }
226
227 int auth_write(int fd, void *data, int length)
228 {
229     if(auth_ok() && data_protection)
230         return ct->write(fd, data, length);
231     else
232         return write(fd, data, length);
233 }
234
235 void auth_vprintf(const char *fmt, va_list ap)
236 {
237     if(auth_ok() && prot_level){
238         ct->vprintf(fmt, ap);
239     }else
240         vprintf(fmt, ap);
241 }
242
243 void auth_printf(const char *fmt, ...)
244 {
245     va_list ap;
246     va_start(ap, fmt);
247     auth_vprintf(fmt, ap);
248     va_end(ap);
249 }