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" },
214 { "debug", 'd', arg_flag
, &debug_flag
},
215 { "interactive", 'i', arg_flag
, &interactive_flag
, "create new socket" },
216 { "port", 'p', arg_string
, &port_str
, "port to listen to", "port" },
217 { "trace-file", 't', arg_string
, &trace_file
, "trace all command to file", "file" },
218 { "timeout", 'T', arg_integer
, &timeout
, "timeout", "seconds" },
219 { "address-log", 0, arg_string
, &addr_log
, "enable address log", "file" },
220 { "help", 'h', arg_flag
, &help_flag
},
221 { "version", 'v', arg_flag
, &version_flag
}
224 static int num_args
= sizeof(args
) / sizeof(args
[0]);
227 * init: Start a Post Office Protocol session
231 pop_getportbyname(POP
*p
, const char *service
,
232 const char *proto
, short def
)
235 return krb5_getportbyname(p
->context
, service
, proto
, def
);
237 return k_getportbyname(service
, proto
, htons(def
));
239 return htons(default);
244 pop_init(POP
*p
,int argcount
,char **argmessage
)
246 struct sockaddr_storage cs_ss
;
247 struct sockaddr
*cs
= (struct sockaddr
*)&cs_ss
;
249 char * trace_file_name
= "/tmp/popper-trace";
254 /* Initialize the POP parameter block */
255 memset (p
, 0, sizeof(POP
));
257 setprogname(argmessage
[0]);
259 /* Save my name in a global variable */
260 p
->myname
= (char*)getprogname();
262 /* Get the name of our host */
263 gethostname(p
->myhost
,MaxHostNameLen
);
269 ret
= krb5_init_context (&p
->context
);
271 errx (1, "krb5_init_context failed: %d", ret
);
273 krb5_openlog(p
->context
, p
->myname
, &p
->logf
);
274 krb5_set_warn_dest(p
->context
, p
->logf
);
277 /* Open the log file */
278 roken_openlog(p
->myname
,POP_LOGOPTS
,POP_FACILITY
);
281 p
->auth_level
= AUTH_NONE
;
283 if(getarg(args
, num_args
, argcount
, argmessage
, &optind
)){
284 arg_printusage(args
, num_args
, NULL
, "");
288 arg_printusage(args
, num_args
, NULL
, "");
297 argmessage
+= optind
;
300 arg_printusage(args
, num_args
, NULL
, "");
305 if (strcmp (auth_str
, "none") == 0)
306 p
->auth_level
= AUTH_NONE
;
307 else if(strcmp(auth_str
, "otp") == 0)
308 p
->auth_level
= AUTH_OTP
;
310 warnx ("bad value for -a: %s", optarg
);
312 /* Debugging requested */
313 p
->debug
= debug_flag
;
316 portnum
= htons(atoi(port_str
));
319 if ((p
->trace
= fopen(trace_file
, "a+")) == NULL
) {
320 pop_log(p
, POP_PRIORITY
,
321 "Unable to open trace file \"%s\", err = %d",
325 trace_file_name
= trace_file
;
328 #if defined(KRB4) || defined(KRB5)
329 p
->kerberosp
= kerberos_flag
;
333 pop_timeout
= timeout
;
336 if (interactive_flag
) {
338 portnum
= p
->kerberosp
?
339 pop_getportbyname(p
, "kpop", "tcp", 1109) :
340 pop_getportbyname(p
, "pop", "tcp", 110);
341 mini_inetd (portnum
);
344 /* Get the address and socket of the client to whom I am speaking */
346 if (getpeername(STDIN_FILENO
, cs
, &len
) < 0) {
347 pop_log(p
,POP_PRIORITY
,
348 "Unable to obtain socket and address of client, err = %d",errno
);
352 /* Save the dotted decimal form of the client's IP address
353 in the POP parameter block */
354 inet_ntop (cs
->sa_family
, socket_get_address (cs
),
355 p
->ipaddr
, sizeof(p
->ipaddr
));
357 /* Save the client's port */
358 p
->ipport
= ntohs(socket_get_port (cs
));
360 /* Get the canonical name of the host to whom I am speaking */
361 error
= getnameinfo_verified (cs
, len
, p
->client
, sizeof(p
->client
),
364 pop_log (p
, POP_PRIORITY
,
365 "getnameinfo: %s", gai_strerror (error
));
366 strlcpy (p
->client
, p
->ipaddr
, sizeof(p
->client
));
369 /* Create input file stream for TCP/IP communication */
370 if ((p
->input
= fdopen(STDIN_FILENO
,"r")) == NULL
){
371 pop_log(p
,POP_PRIORITY
,
372 "Unable to open communication stream for input, err = %d",errno
);
376 /* Create output file stream for TCP/IP communication */
377 if ((p
->output
= fdopen(STDOUT_FILENO
,"w")) == NULL
){
378 pop_log(p
,POP_PRIORITY
,
379 "Unable to open communication stream for output, err = %d",errno
);
383 pop_log(p
,POP_PRIORITY
,
384 "(v%s) Servicing request from \"%s\" at %s\n",
385 VERSION
,p
->client
,p
->ipaddr
);
389 pop_log(p
,POP_PRIORITY
,
390 "Tracing session and debugging information in file \"%s\"",
393 pop_log(p
,POP_PRIORITY
,"Debugging turned on");
398 return krb_authenticate(p
, cs
);
400 return plain_authenticate(p
, cs
);