No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / appl / popper / pop_init.c
blob7cbf5bf3ee23a75cd020c714892c3db43cb5d9d6
1 /*
2 * Copyright (c) 1989 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
7 #include <popper.h>
8 __RCSID("$Heimdal: pop_init.c 17450 2006-05-05 11:11:43Z lha $"
9 "$NetBSD$");
12 #if defined(KRB4) || defined(KRB5)
14 static int
15 pop_net_read(POP *p, int fd, void *buf, size_t len)
17 #ifdef KRB5
18 return krb5_net_read(p->context, &fd, buf, len);
19 #elif defined(KRB4)
20 return krb_net_read(fd, buf, len);
21 #endif
23 #endif
25 static char *addr_log;
27 static void
28 pop_write_addr(POP *p, struct sockaddr *addr)
30 char ts[32];
31 char as[128];
32 time_t t;
33 FILE *f;
34 if(addr_log == NULL)
35 return;
36 t = time(NULL);
37 strftime(ts, sizeof(ts), "%Y%m%d%H%M%S", localtime(&t));
38 if(inet_ntop (addr->sa_family, socket_get_address(addr),
39 as, sizeof(as)) == NULL) {
40 pop_log(p, POP_PRIORITY, "failed to print address");
41 return;
44 f = fopen(addr_log, "a");
45 if(f == NULL) {
46 pop_log(p, POP_PRIORITY, "failed to open address log (%s)", addr_log);
47 return;
49 fprintf(f, "%s %s\n", as, ts);
50 fclose(f);
53 #ifdef KRB4
54 static int
55 krb4_authenticate (POP *p, int s, u_char *buf, struct sockaddr *addr)
57 Key_schedule schedule;
58 KTEXT_ST ticket;
59 char instance[INST_SZ];
60 char version[9];
61 int auth;
63 if (memcmp (buf, KRB_SENDAUTH_VERS, 4) != 0)
64 return -1;
65 if (pop_net_read (p, s, buf + 4,
66 KRB_SENDAUTH_VLEN - 4) != KRB_SENDAUTH_VLEN - 4)
67 return -1;
68 if (memcmp (buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN) != 0)
69 return -1;
71 k_getsockinst (0, instance, sizeof(instance));
72 auth = krb_recvauth(KOPT_IGNORE_PROTOCOL,
74 &ticket,
75 "pop",
76 instance,
77 (struct sockaddr_in *)addr,
78 (struct sockaddr_in *) NULL,
79 &p->kdata,
80 "",
81 schedule,
82 version);
84 if (auth != KSUCCESS) {
85 pop_msg(p, POP_FAILURE, "Kerberos authentication failure: %s",
86 krb_get_err_text(auth));
87 pop_log(p, POP_PRIORITY, "%s: (%s.%s@%s) %s", p->client,
88 p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
89 krb_get_err_text(auth));
90 return -1;
93 #ifdef DEBUG
94 pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", p->kdata.pname,
95 p->kdata.pinst, p->kdata.prealm, p->ipaddr);
96 #endif /* DEBUG */
97 return 0;
99 #endif /* KRB4 */
101 #ifdef KRB5
102 static int
103 krb5_authenticate (POP *p, int s, u_char *buf, struct sockaddr *addr)
105 krb5_error_code ret;
106 krb5_auth_context auth_context = NULL;
107 uint32_t len;
108 krb5_ticket *ticket;
109 char *server;
111 if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
112 return -1;
113 len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
115 if (krb5_net_read(p->context, &s, buf, len) != len)
116 return -1;
117 if (len != sizeof(KRB5_SENDAUTH_VERSION)
118 || memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
119 return -1;
121 ret = krb5_recvauth (p->context,
122 &auth_context,
124 "KPOPV1.0",
125 NULL, /* let rd_req figure out what server to use */
126 KRB5_RECVAUTH_IGNORE_VERSION,
127 NULL,
128 &ticket);
129 if (ret) {
130 pop_log(p, POP_PRIORITY, "krb5_recvauth: %s",
131 krb5_get_err_text(p->context, ret));
132 return -1;
136 ret = krb5_unparse_name(p->context, ticket->server, &server);
137 if(ret) {
138 pop_log(p, POP_PRIORITY, "krb5_unparse_name: %s",
139 krb5_get_err_text(p->context, ret));
140 ret = -1;
141 goto out;
143 /* does this make sense? */
144 if(strncmp(server, "pop/", 4) != 0) {
145 pop_log(p, POP_PRIORITY,
146 "Got ticket for service `%s'", server);
147 ret = -1;
148 goto out;
149 } else if(p->debug)
150 pop_log(p, POP_DEBUG,
151 "Accepted ticket for service `%s'", server);
152 free(server);
153 out:
154 krb5_auth_con_free (p->context, auth_context);
155 krb5_copy_principal (p->context, ticket->client, &p->principal);
156 krb5_free_ticket (p->context, ticket);
158 return ret;
160 #endif
162 static int
163 krb_authenticate(POP *p, struct sockaddr *addr)
165 #if defined(KRB4) || defined(KRB5)
166 u_char buf[BUFSIZ];
168 if (pop_net_read (p, 0, buf, 4) != 4) {
169 pop_msg(p, POP_FAILURE, "Reading four bytes: %s",
170 strerror(errno));
171 exit (1);
173 #ifdef KRB4
174 if (krb4_authenticate (p, 0, buf, addr) == 0){
175 pop_write_addr(p, addr);
176 p->version = 4;
177 return POP_SUCCESS;
179 #endif
180 #ifdef KRB5
181 if (krb5_authenticate (p, 0, buf, addr) == 0){
182 pop_write_addr(p, addr);
183 p->version = 5;
184 return POP_SUCCESS;
186 #endif
187 exit (1);
189 #endif /* defined(KRB4) || defined(KRB5) */
191 return(POP_SUCCESS);
194 static int
195 plain_authenticate (POP *p, struct sockaddr *addr)
197 return(POP_SUCCESS);
200 static int kerberos_flag;
201 static char *auth_str;
202 static int debug_flag;
203 static int interactive_flag;
204 static char *port_str;
205 static char *trace_file;
206 static int timeout;
207 static int help_flag;
208 static int version_flag;
210 static struct getargs args[] = {
211 #if defined(KRB4) || defined(KRB5)
212 { "kerberos", 'k', arg_flag, &kerberos_flag, "use kerberos" },
213 #endif
214 { "auth-mode", 'a', arg_string, &auth_str, "required authentication",
215 "plaintext"
216 #ifdef OTP
217 "|otp"
218 #endif
219 #ifdef SASL
220 "|sasl"
221 #endif
223 { "debug", 'd', arg_flag, &debug_flag },
224 { "interactive", 'i', arg_flag, &interactive_flag, "create new socket" },
225 { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
226 { "trace-file", 't', arg_string, &trace_file, "trace all command to file", "file" },
227 { "timeout", 'T', arg_integer, &timeout, "timeout", "seconds" },
228 { "address-log", 0, arg_string, &addr_log, "enable address log", "file" },
229 { "help", 'h', arg_flag, &help_flag },
230 { "version", 'v', arg_flag, &version_flag }
233 static int num_args = sizeof(args) / sizeof(args[0]);
236 * init: Start a Post Office Protocol session
239 static int
240 pop_getportbyname(POP *p, const char *service,
241 const char *proto, short def)
243 #ifdef KRB5
244 return krb5_getportbyname(p->context, service, proto, def);
245 #elif defined(KRB4)
246 return k_getportbyname(service, proto, htons(def));
247 #else
248 return htons(default);
249 #endif
253 pop_init(POP *p,int argcount,char **argmessage)
255 struct sockaddr_storage cs_ss;
256 struct sockaddr *cs = (struct sockaddr *)&cs_ss;
257 socklen_t len;
258 char * trace_file_name = "/tmp/popper-trace";
259 int portnum = 0;
260 int optind = 0;
261 int error;
263 /* Initialize the POP parameter block */
264 memset (p, 0, sizeof(POP));
266 setprogname(argmessage[0]);
268 /* Save my name in a global variable */
269 p->myname = (char*)getprogname();
271 /* Get the name of our host */
272 gethostname(p->myhost,MaxHostNameLen);
274 #ifdef KRB5
276 krb5_error_code ret;
278 ret = krb5_init_context (&p->context);
279 if (ret)
280 errx (1, "krb5_init_context failed: %d", ret);
282 krb5_openlog(p->context, p->myname, &p->logf);
283 krb5_set_warn_dest(p->context, p->logf);
285 #else
286 /* Open the log file */
287 roken_openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
288 #endif
290 p->auth_level = AUTH_NONE;
292 if(getarg(args, num_args, argcount, argmessage, &optind)){
293 arg_printusage(args, num_args, NULL, "");
294 exit(1);
296 if(help_flag){
297 arg_printusage(args, num_args, NULL, "");
298 exit(0);
300 if(version_flag){
301 print_version(NULL);
302 exit(0);
305 argcount -= optind;
306 argmessage += optind;
308 if (argcount != 0) {
309 arg_printusage(args, num_args, NULL, "");
310 exit(1);
313 if(auth_str){
314 if (strcasecmp (auth_str, "plaintext") == 0 ||
315 strcasecmp (auth_str, "none") == 0)
316 p->auth_level = AUTH_NONE;
317 else if(strcasecmp(auth_str, "otp") == 0) {
318 #ifdef OTP
319 p->auth_level = AUTH_OTP;
320 #else
321 pop_log (p, POP_PRIORITY, "support for OTP not enabled");
322 exit(1);
323 #endif
324 } else if(strcasecmp(auth_str, "sasl") == 0) {
325 #ifdef SASL
326 p->auth_level = AUTH_SASL;
327 #else
328 pop_log (p, POP_PRIORITY, "support for SASL not enabled");
329 exit(1);
330 #endif
331 } else {
332 pop_log (p, POP_PRIORITY, "bad value for -a: %s", auth_str);
333 exit(1);
336 /* Debugging requested */
337 p->debug = debug_flag;
339 if(port_str)
340 portnum = htons(atoi(port_str));
341 if(trace_file){
342 p->debug++;
343 if ((p->trace = fopen(trace_file, "a+")) == NULL) {
344 pop_log(p, POP_PRIORITY,
345 "Unable to open trace file \"%s\", err = %d",
346 optarg,errno);
347 exit (1);
349 trace_file_name = trace_file;
352 #if defined(KRB4) || defined(KRB5)
353 p->kerberosp = kerberos_flag;
354 #endif
356 if(timeout)
357 pop_timeout = timeout;
359 /* Fake inetd */
360 if (interactive_flag) {
361 if (portnum == 0)
362 portnum = p->kerberosp ?
363 pop_getportbyname(p, "kpop", "tcp", 1109) :
364 pop_getportbyname(p, "pop", "tcp", 110);
365 mini_inetd (portnum);
368 /* Get the address and socket of the client to whom I am speaking */
369 len = sizeof(cs_ss);
370 if (getpeername(STDIN_FILENO, cs, &len) < 0) {
371 pop_log(p,POP_PRIORITY,
372 "Unable to obtain socket and address of client, err = %d",errno);
373 exit (1);
376 /* Save the dotted decimal form of the client's IP address
377 in the POP parameter block */
378 inet_ntop (cs->sa_family, socket_get_address (cs),
379 p->ipaddr, sizeof(p->ipaddr));
381 /* Save the client's port */
382 p->ipport = ntohs(socket_get_port (cs));
384 /* Get the canonical name of the host to whom I am speaking */
385 error = getnameinfo_verified (cs, len, p->client, sizeof(p->client),
386 NULL, 0, 0);
387 if (error) {
388 pop_log (p, POP_PRIORITY,
389 "getnameinfo: %s", gai_strerror (error));
390 strlcpy (p->client, p->ipaddr, sizeof(p->client));
393 /* Create input file stream for TCP/IP communication */
394 if ((p->input = fdopen(STDIN_FILENO,"r")) == NULL){
395 pop_log(p,POP_PRIORITY,
396 "Unable to open communication stream for input, err = %d",errno);
397 exit (1);
400 /* Create output file stream for TCP/IP communication */
401 if ((p->output = fdopen(STDOUT_FILENO,"w")) == NULL){
402 pop_log(p,POP_PRIORITY,
403 "Unable to open communication stream for output, err = %d",errno);
404 exit (1);
407 pop_log(p,POP_PRIORITY,
408 "(v%s) Servicing request from \"%s\" at %s\n",
409 VERSION,p->client,p->ipaddr);
411 #ifdef DEBUG
412 if (p->trace)
413 pop_log(p,POP_PRIORITY,
414 "Tracing session and debugging information in file \"%s\"",
415 trace_file_name);
416 else if (p->debug)
417 pop_log(p,POP_PRIORITY,"Debugging turned on");
418 #endif /* DEBUG */
421 if(p->kerberosp)
422 return krb_authenticate(p, cs);
423 else
424 return plain_authenticate(p, cs);