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.
11 #if defined(KRB4) || defined(KRB5)
14 pop_net_read(POP
*p
, int fd
, void *buf
, size_t len
)
17 return krb5_net_read(p
->context
, &fd
, buf
, len
);
19 return krb_net_read(fd
, buf
, len
);
24 static char *addr_log
;
27 pop_write_addr(POP
*p
, struct sockaddr
*addr
)
36 strftime(ts
, sizeof(ts
), "%Y%m%d%H%M%S", localtime(&t
));
37 if(inet_ntop (addr
->sa_family
, socket_get_address(addr
),
38 as
, sizeof(as
)) == NULL
) {
39 pop_log(p
, POP_PRIORITY
, "failed to print address");
43 f
= fopen(addr_log
, "a");
45 pop_log(p
, POP_PRIORITY
, "failed to open address log (%s)", addr_log
);
48 fprintf(f
, "%s %s\n", as
, ts
);
54 krb4_authenticate (POP
*p
, int s
, u_char
*buf
, struct sockaddr
*addr
)
56 Key_schedule schedule
;
58 char instance
[INST_SZ
];
62 if (memcmp (buf
, KRB_SENDAUTH_VERS
, 4) != 0)
64 if (pop_net_read (p
, s
, buf
+ 4,
65 KRB_SENDAUTH_VLEN
- 4) != KRB_SENDAUTH_VLEN
- 4)
67 if (memcmp (buf
, KRB_SENDAUTH_VERS
, KRB_SENDAUTH_VLEN
) != 0)
70 k_getsockinst (0, instance
, sizeof(instance
));
71 auth
= krb_recvauth(KOPT_IGNORE_PROTOCOL
,
76 (struct sockaddr_in
*)addr
,
77 (struct sockaddr_in
*) NULL
,
83 if (auth
!= KSUCCESS
) {
84 pop_msg(p
, POP_FAILURE
, "Kerberos authentication failure: %s",
85 krb_get_err_text(auth
));
86 pop_log(p
, POP_PRIORITY
, "%s: (%s.%s@%s) %s", p
->client
,
87 p
->kdata
.pname
, p
->kdata
.pinst
, p
->kdata
.prealm
,
88 krb_get_err_text(auth
));
93 pop_log(p
, POP_DEBUG
, "%s.%s@%s (%s): ok", p
->kdata
.pname
,
94 p
->kdata
.pinst
, p
->kdata
.prealm
, p
->ipaddr
);
102 krb5_authenticate (POP
*p
, int s
, u_char
*buf
, struct sockaddr
*addr
)
105 krb5_auth_context auth_context
= NULL
;
110 if (memcmp (buf
, "\x00\x00\x00\x13", 4) != 0)
112 len
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | (buf
[3]);
114 if (krb5_net_read(p
->context
, &s
, buf
, len
) != len
)
116 if (len
!= sizeof(KRB5_SENDAUTH_VERSION
)
117 || memcmp (buf
, KRB5_SENDAUTH_VERSION
, len
) != 0)
120 ret
= krb5_recvauth (p
->context
,
124 NULL
, /* let rd_req figure out what server to use */
125 KRB5_RECVAUTH_IGNORE_VERSION
,
129 pop_log(p
, POP_PRIORITY
, "krb5_recvauth: %s",
130 krb5_get_err_text(p
->context
, ret
));
135 ret
= krb5_unparse_name(p
->context
, ticket
->server
, &server
);
137 pop_log(p
, POP_PRIORITY
, "krb5_unparse_name: %s",
138 krb5_get_err_text(p
->context
, ret
));
142 /* does this make sense? */
143 if(strncmp(server
, "pop/", 4) != 0) {
144 pop_log(p
, POP_PRIORITY
,
145 "Got ticket for service `%s'", server
);
149 pop_log(p
, POP_DEBUG
,
150 "Accepted ticket for service `%s'", server
);
153 krb5_auth_con_free (p
->context
, auth_context
);
154 krb5_copy_principal (p
->context
, ticket
->client
, &p
->principal
);
155 krb5_free_ticket (p
->context
, ticket
);
162 krb_authenticate(POP
*p
, struct sockaddr
*addr
)
164 #if defined(KRB4) || defined(KRB5)
167 if (pop_net_read (p
, 0, buf
, 4) != 4) {
168 pop_msg(p
, POP_FAILURE
, "Reading four bytes: %s",
173 if (krb4_authenticate (p
, 0, buf
, addr
) == 0){
174 pop_write_addr(p
, addr
);
180 if (krb5_authenticate (p
, 0, buf
, addr
) == 0){
181 pop_write_addr(p
, addr
);
188 #endif /* defined(KRB4) || defined(KRB5) */
194 plain_authenticate (POP
*p
, struct sockaddr
*addr
)
199 static int kerberos_flag
;
200 static char *auth_str
;
201 static int debug_flag
;
202 static int interactive_flag
;
203 static char *port_str
;
204 static char *trace_file
;
206 static int help_flag
;
207 static int version_flag
;
209 static struct getargs args
[] = {
210 #if defined(KRB4) || defined(KRB5)
211 { "kerberos", 'k', arg_flag
, &kerberos_flag
, "use kerberos" },
213 { "auth-mode", 'a', arg_string
, &auth_str
, "required authentication",
222 { "debug", 'd', arg_flag
, &debug_flag
},
223 { "interactive", 'i', arg_flag
, &interactive_flag
, "create new socket" },
224 { "port", 'p', arg_string
, &port_str
, "port to listen to", "port" },
225 { "trace-file", 't', arg_string
, &trace_file
, "trace all command to file", "file" },
226 { "timeout", 'T', arg_integer
, &timeout
, "timeout", "seconds" },
227 { "address-log", 0, arg_string
, &addr_log
, "enable address log", "file" },
228 { "help", 'h', arg_flag
, &help_flag
},
229 { "version", 'v', arg_flag
, &version_flag
}
232 static int num_args
= sizeof(args
) / sizeof(args
[0]);
235 * init: Start a Post Office Protocol session
239 pop_getportbyname(POP
*p
, const char *service
,
240 const char *proto
, short def
)
243 return krb5_getportbyname(p
->context
, service
, proto
, def
);
245 return k_getportbyname(service
, proto
, htons(def
));
247 return htons(default);
252 pop_init(POP
*p
,int argcount
,char **argmessage
)
254 struct sockaddr_storage cs_ss
;
255 struct sockaddr
*cs
= (struct sockaddr
*)&cs_ss
;
257 char * trace_file_name
= "/tmp/popper-trace";
262 /* Initialize the POP parameter block */
263 memset (p
, 0, sizeof(POP
));
265 setprogname(argmessage
[0]);
267 /* Save my name in a global variable */
268 p
->myname
= (char*)getprogname();
270 /* Get the name of our host */
271 gethostname(p
->myhost
,MaxHostNameLen
);
277 ret
= krb5_init_context (&p
->context
);
279 errx (1, "krb5_init_context failed: %d", ret
);
281 krb5_openlog(p
->context
, p
->myname
, &p
->logf
);
282 krb5_set_warn_dest(p
->context
, p
->logf
);
285 /* Open the log file */
286 roken_openlog(p
->myname
,POP_LOGOPTS
,POP_FACILITY
);
289 p
->auth_level
= AUTH_NONE
;
291 if(getarg(args
, num_args
, argcount
, argmessage
, &optind
)){
292 arg_printusage(args
, num_args
, NULL
, "");
296 arg_printusage(args
, num_args
, NULL
, "");
305 argmessage
+= optind
;
308 arg_printusage(args
, num_args
, NULL
, "");
313 if (strcasecmp (auth_str
, "plaintext") == 0 ||
314 strcasecmp (auth_str
, "none") == 0)
315 p
->auth_level
= AUTH_NONE
;
316 else if(strcasecmp(auth_str
, "otp") == 0) {
318 p
->auth_level
= AUTH_OTP
;
320 pop_log (p
, POP_PRIORITY
, "support for OTP not enabled");
323 } else if(strcasecmp(auth_str
, "sasl") == 0) {
325 p
->auth_level
= AUTH_SASL
;
327 pop_log (p
, POP_PRIORITY
, "support for SASL not enabled");
331 pop_log (p
, POP_PRIORITY
, "bad value for -a: %s", auth_str
);
335 /* Debugging requested */
336 p
->debug
= debug_flag
;
339 portnum
= htons(atoi(port_str
));
342 if ((p
->trace
= fopen(trace_file
, "a+")) == NULL
) {
343 pop_log(p
, POP_PRIORITY
,
344 "Unable to open trace file \"%s\", err = %d",
348 trace_file_name
= trace_file
;
351 #if defined(KRB4) || defined(KRB5)
352 p
->kerberosp
= kerberos_flag
;
356 pop_timeout
= timeout
;
359 if (interactive_flag
) {
361 portnum
= p
->kerberosp
?
362 pop_getportbyname(p
, "kpop", "tcp", 1109) :
363 pop_getportbyname(p
, "pop", "tcp", 110);
364 mini_inetd (portnum
);
367 /* Get the address and socket of the client to whom I am speaking */
369 if (getpeername(STDIN_FILENO
, cs
, &len
) < 0) {
370 pop_log(p
,POP_PRIORITY
,
371 "Unable to obtain socket and address of client, err = %d",errno
);
375 /* Save the dotted decimal form of the client's IP address
376 in the POP parameter block */
377 inet_ntop (cs
->sa_family
, socket_get_address (cs
),
378 p
->ipaddr
, sizeof(p
->ipaddr
));
380 /* Save the client's port */
381 p
->ipport
= ntohs(socket_get_port (cs
));
383 /* Get the canonical name of the host to whom I am speaking */
384 error
= getnameinfo_verified (cs
, len
, p
->client
, sizeof(p
->client
),
387 pop_log (p
, POP_PRIORITY
,
388 "getnameinfo: %s", gai_strerror (error
));
389 strlcpy (p
->client
, p
->ipaddr
, sizeof(p
->client
));
392 /* Create input file stream for TCP/IP communication */
393 if ((p
->input
= fdopen(STDIN_FILENO
,"r")) == NULL
){
394 pop_log(p
,POP_PRIORITY
,
395 "Unable to open communication stream for input, err = %d",errno
);
399 /* Create output file stream for TCP/IP communication */
400 if ((p
->output
= fdopen(STDOUT_FILENO
,"w")) == NULL
){
401 pop_log(p
,POP_PRIORITY
,
402 "Unable to open communication stream for output, err = %d",errno
);
406 pop_log(p
,POP_PRIORITY
,
407 "(v%s) Servicing request from \"%s\" at %s\n",
408 VERSION
,p
->client
,p
->ipaddr
);
412 pop_log(p
,POP_PRIORITY
,
413 "Tracing session and debugging information in file \"%s\"",
416 pop_log(p
,POP_PRIORITY
,"Debugging turned on");
421 return krb_authenticate(p
, cs
);
423 return plain_authenticate(p
, cs
);