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.
8 __RCSID("$Heimdal: pop_init.c 17450 2006-05-05 11:11:43Z lha $"
12 #if defined(KRB4) || defined(KRB5)
15 pop_net_read(POP
*p
, int fd
, void *buf
, size_t len
)
18 return krb5_net_read(p
->context
, &fd
, buf
, len
);
20 return krb_net_read(fd
, buf
, len
);
25 static char *addr_log
;
28 pop_write_addr(POP
*p
, struct sockaddr
*addr
)
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");
44 f
= fopen(addr_log
, "a");
46 pop_log(p
, POP_PRIORITY
, "failed to open address log (%s)", addr_log
);
49 fprintf(f
, "%s %s\n", as
, ts
);
55 krb4_authenticate (POP
*p
, int s
, u_char
*buf
, struct sockaddr
*addr
)
57 Key_schedule schedule
;
59 char instance
[INST_SZ
];
63 if (memcmp (buf
, KRB_SENDAUTH_VERS
, 4) != 0)
65 if (pop_net_read (p
, s
, buf
+ 4,
66 KRB_SENDAUTH_VLEN
- 4) != KRB_SENDAUTH_VLEN
- 4)
68 if (memcmp (buf
, KRB_SENDAUTH_VERS
, KRB_SENDAUTH_VLEN
) != 0)
71 k_getsockinst (0, instance
, sizeof(instance
));
72 auth
= krb_recvauth(KOPT_IGNORE_PROTOCOL
,
77 (struct sockaddr_in
*)addr
,
78 (struct sockaddr_in
*) NULL
,
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
));
94 pop_log(p
, POP_DEBUG
, "%s.%s@%s (%s): ok", p
->kdata
.pname
,
95 p
->kdata
.pinst
, p
->kdata
.prealm
, p
->ipaddr
);
103 krb5_authenticate (POP
*p
, int s
, u_char
*buf
, struct sockaddr
*addr
)
106 krb5_auth_context auth_context
= NULL
;
111 if (memcmp (buf
, "\x00\x00\x00\x13", 4) != 0)
113 len
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | (buf
[3]);
115 if (krb5_net_read(p
->context
, &s
, buf
, len
) != len
)
117 if (len
!= sizeof(KRB5_SENDAUTH_VERSION
)
118 || memcmp (buf
, KRB5_SENDAUTH_VERSION
, len
) != 0)
121 ret
= krb5_recvauth (p
->context
,
125 NULL
, /* let rd_req figure out what server to use */
126 KRB5_RECVAUTH_IGNORE_VERSION
,
130 pop_log(p
, POP_PRIORITY
, "krb5_recvauth: %s",
131 krb5_get_err_text(p
->context
, ret
));
136 ret
= krb5_unparse_name(p
->context
, ticket
->server
, &server
);
138 pop_log(p
, POP_PRIORITY
, "krb5_unparse_name: %s",
139 krb5_get_err_text(p
->context
, ret
));
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
);
150 pop_log(p
, POP_DEBUG
,
151 "Accepted ticket for service `%s'", server
);
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
);
163 krb_authenticate(POP
*p
, struct sockaddr
*addr
)
165 #if defined(KRB4) || defined(KRB5)
168 if (pop_net_read (p
, 0, buf
, 4) != 4) {
169 pop_msg(p
, POP_FAILURE
, "Reading four bytes: %s",
174 if (krb4_authenticate (p
, 0, buf
, addr
) == 0){
175 pop_write_addr(p
, addr
);
181 if (krb5_authenticate (p
, 0, buf
, addr
) == 0){
182 pop_write_addr(p
, addr
);
189 #endif /* defined(KRB4) || defined(KRB5) */
195 plain_authenticate (POP
*p
, struct sockaddr
*addr
)
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
;
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" },
214 { "auth-mode", 'a', arg_string
, &auth_str
, "required authentication",
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
240 pop_getportbyname(POP
*p
, const char *service
,
241 const char *proto
, short def
)
244 return krb5_getportbyname(p
->context
, service
, proto
, def
);
246 return k_getportbyname(service
, proto
, htons(def
));
248 return htons(default);
253 pop_init(POP
*p
,int argcount
,char **argmessage
)
255 struct sockaddr_storage cs_ss
;
256 struct sockaddr
*cs
= (struct sockaddr
*)&cs_ss
;
258 char * trace_file_name
= "/tmp/popper-trace";
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
);
278 ret
= krb5_init_context (&p
->context
);
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
);
286 /* Open the log file */
287 roken_openlog(p
->myname
,POP_LOGOPTS
,POP_FACILITY
);
290 p
->auth_level
= AUTH_NONE
;
292 if(getarg(args
, num_args
, argcount
, argmessage
, &optind
)){
293 arg_printusage(args
, num_args
, NULL
, "");
297 arg_printusage(args
, num_args
, NULL
, "");
306 argmessage
+= optind
;
309 arg_printusage(args
, num_args
, NULL
, "");
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) {
319 p
->auth_level
= AUTH_OTP
;
321 pop_log (p
, POP_PRIORITY
, "support for OTP not enabled");
324 } else if(strcasecmp(auth_str
, "sasl") == 0) {
326 p
->auth_level
= AUTH_SASL
;
328 pop_log (p
, POP_PRIORITY
, "support for SASL not enabled");
332 pop_log (p
, POP_PRIORITY
, "bad value for -a: %s", auth_str
);
336 /* Debugging requested */
337 p
->debug
= debug_flag
;
340 portnum
= htons(atoi(port_str
));
343 if ((p
->trace
= fopen(trace_file
, "a+")) == NULL
) {
344 pop_log(p
, POP_PRIORITY
,
345 "Unable to open trace file \"%s\", err = %d",
349 trace_file_name
= trace_file
;
352 #if defined(KRB4) || defined(KRB5)
353 p
->kerberosp
= kerberos_flag
;
357 pop_timeout
= timeout
;
360 if (interactive_flag
) {
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 */
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
);
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
),
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
);
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
);
407 pop_log(p
,POP_PRIORITY
,
408 "(v%s) Servicing request from \"%s\" at %s\n",
409 VERSION
,p
->client
,p
->ipaddr
);
413 pop_log(p
,POP_PRIORITY
,
414 "Tracing session and debugging information in file \"%s\"",
417 pop_log(p
,POP_PRIORITY
,"Debugging turned on");
422 return krb_authenticate(p
, cs
);
424 return plain_authenticate(p
, cs
);