#include "k5-int.h"
#include "com_err.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <syslog.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "../sample.h"
extern krb5_deltat krb5_clockskew;
#ifndef GETPEERNAME_ARG3_TYPE
#define GETPEERNAME_ARG3_TYPE int
#endif
#define DEBUG
static void
usage(name)
char *name;
{
fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n",
name);
}
int
main(argc, argv)
int argc;
char *argv[];
{
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_ticket * ticket;
struct sockaddr_in peername;
GETPEERNAME_ARG3_TYPE namelen = sizeof(peername);
int sock = -1;
krb5_data recv_data;
short xmitlen;
krb5_error_code retval;
krb5_principal server;
char repbuf[BUFSIZ];
char *cname;
char *service = SAMPLE_SERVICE;
short port = 0;
extern int opterr, optind;
extern char * optarg;
int ch;
krb5_keytab keytab = NULL;
char *progname;
int on = 1;
progname = *argv;
retval = krb5_init_context(&context);
if (retval) {
com_err(argv[0], retval, "while initializing krb5");
exit(1);
}
openlog("sserver", 0, LOG_DAEMON);
opterr = 0;
while ((ch = getopt(argc, argv, "p:S:s:")) != -1)
switch (ch) {
case 'p':
port = atoi(optarg);
break;
case 's':
service = optarg;
break;
case 'S':
if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
com_err(progname, retval,
"while resolving keytab file %s", optarg);
exit(2);
}
break;
case '?':
default:
usage(progname);
exit(1);
break;
}
argc -= optind;
argv += optind;
if (argc > 1) {
port = atoi(argv[1]);
}
retval = krb5_sname_to_principal(context, NULL, service,
KRB5_NT_SRV_HST, &server);
if (retval) {
syslog(LOG_ERR, "while generating service name (%s): %s",
service, error_message(retval));
exit(1);
}
if (port) {
int acc;
struct sockaddr_in sockin;
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
syslog(LOG_ERR, "socket: %m");
exit(3);
}
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on));
sockin.sin_family = AF_INET;
sockin.sin_addr.s_addr = 0;
sockin.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &sockin, sizeof(sockin))) {
syslog(LOG_ERR, "bind: %m");
exit(3);
}
if (listen(sock, 1) == -1) {
syslog(LOG_ERR, "listen: %m");
exit(3);
}
if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){
syslog(LOG_ERR, "accept: %m");
exit(3);
}
dup2(acc, 0);
close(sock);
sock = 0;
} else {
if (getpeername(0, (struct sockaddr *)&peername, &namelen) < 0) {
syslog(LOG_ERR, "getpeername: %m");
exit(1);
}
sock = 0;
}
retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock,
SAMPLE_VERSION, server,
0,
keytab,
&ticket);
if (retval) {
syslog(LOG_ERR, "recvauth failed--%s", error_message(retval));
exit(1);
}
retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname);
if (retval){
syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
sprintf(repbuf, "You are <unparse error>\n");
} else {
sprintf(repbuf, "You are %s\n", cname);
free(cname);
}
xmitlen = htons(strlen(repbuf));
recv_data.length = strlen(repbuf);
recv_data.data = repbuf;
if ((retval = krb5_net_write(context, 0, (char *)&xmitlen,
sizeof(xmitlen))) < 0) {
syslog(LOG_ERR, "%m: while writing len to client");
exit(1);
}
if ((retval = krb5_net_write(context, 0, (char *)recv_data.data,
recv_data.length)) < 0) {
syslog(LOG_ERR, "%m: while writing data to client");
exit(1);
}
krb5_free_ticket(context, ticket);
if(keytab)
krb5_kt_close(context, keytab);
krb5_free_principal(context, server);
krb5_auth_con_free(context, auth_context);
krb5_free_context(context);
exit(0);
}