From 3447488a94e78b75102b357c2d83e18684939cb5 Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Mon, 10 May 1999 00:16:50 +0000 Subject: [PATCH] (main): use getarg (*): handle v4 and/or v5 git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@6183 ec53bebd-3082-4978-b11e-865c3cabbd6b --- appl/kx/kx.c | 411 +++++++++++++++++++++++++++++++------------------- appl/kx/kxd.c | 373 ++++++++++++++++++++++----------------------- 2 files changed, 439 insertions(+), 345 deletions(-) diff --git a/appl/kx/kx.c b/appl/kx/kx.c index 36115fb87..2d5d3ab76 100644 --- a/appl/kx/kx.c +++ b/appl/kx/kx.c @@ -97,39 +97,34 @@ usr2handler (int sig) */ static int -connect_host (char *host, char *user, des_cblock *key, - des_key_schedule schedule, int port, - struct sockaddr_in *thisaddr, - struct sockaddr_in *thataddr) +connect_host (kx_context *kc) { - CREDENTIALS cred; - KTEXT_ST text; - MSG_DAT msg; - int status; int addrlen; struct hostent *hostent; int s; char **p; + struct sockaddr_in thisaddr; + struct sockaddr_in thataddr; - hostent = gethostbyname (host); + hostent = gethostbyname (kc->host); if (hostent == NULL) { - warnx ("gethostbyname '%s' failed: %s", host, + warnx ("gethostbyname '%s' failed: %s", kc->host, hstrerror(h_errno)); return -1; } - memset (thataddr, 0, sizeof(*thataddr)); - thataddr->sin_family = AF_INET; - thataddr->sin_port = port; + memset (&thataddr, 0, sizeof(thataddr)); + thataddr.sin_family = AF_INET; + thataddr.sin_port = kc->port; for(p = hostent->h_addr_list; *p; ++p) { - memcpy (&thataddr->sin_addr, *p, sizeof(thataddr->sin_addr)); + memcpy (&thataddr.sin_addr, *p, sizeof(thataddr.sin_addr)); s = socket (AF_INET, SOCK_STREAM, 0); if (s < 0) err (1, "socket"); - if (connect (s, (struct sockaddr *)thataddr, sizeof(*thataddr)) < 0) { - warn ("connect(%s)", host); + if (connect (s, (struct sockaddr *)&thataddr, sizeof(thataddr)) < 0) { + warn ("connect(%s)", kc->host); close (s); continue; } else { @@ -139,19 +134,14 @@ connect_host (char *host, char *user, des_cblock *key, if (*p == NULL) return -1; - addrlen = sizeof(*thisaddr); - if (getsockname (s, (struct sockaddr *)thisaddr, &addrlen) < 0 || - addrlen != sizeof(*thisaddr)) - err(1, "getsockname(%s)", host); - status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd", - host, krb_realmofhost (host), - getpid(), &msg, &cred, schedule, - thisaddr, thataddr, KX_VERSION); - if (status != KSUCCESS) { - warnx ("%s: %s\n", host, krb_get_err_text(status)); + addrlen = sizeof(thisaddr); + if (getsockname (s, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) + err(1, "getsockname(%s)", kc->host); + kc->thisaddr = thisaddr; + kc->thataddr = thataddr; + if ((*kc->authenticate)(kc, s)) return -1; - } - memcpy(key, cred.session, sizeof(des_cblock)); return s; } @@ -161,23 +151,21 @@ connect_host (char *host, char *user, des_cblock *key, */ static int -passive_session (int xserver, int fd, des_cblock *iv, - des_key_schedule schedule) +passive_session (int xserver, int fd, kx_context *kc) { if (replace_cookie (xserver, fd, XauFileName(), 1)) return 1; else - return copy_encrypted (xserver, fd, iv, schedule); + return copy_encrypted (kc, xserver, fd); } static int -active_session (int xserver, int fd, des_cblock *iv, - des_key_schedule schedule) +active_session (int xserver, int fd, kx_context *kc) { if (verify_and_remove_cookies (xserver, fd, 1)) return 1; else - return copy_encrypted (xserver, fd, iv, schedule); + return copy_encrypted (kc, xserver, fd); } static void @@ -208,24 +196,20 @@ status_output (int debugp) */ static int -doit_passive (char *host, char *user, int debugp, int keepalivep, - int port) +doit_passive (kx_context *kc) { - des_key_schedule schedule; - des_cblock key; int otherside; - struct sockaddr_in me, him; u_char msg[1024], *p; int len; - void *ret; u_int32_t tmp; + char *host = kc->host; + + otherside = connect_host (kc); - otherside = connect_host (host, user, &key, schedule, port, - &me, &him); if (otherside < 0) return 1; #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) - if (keepalivep) { + if (kc->keepalive_flag) { int one = 1; setsockopt (otherside, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, @@ -235,22 +219,20 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, p = msg; *p++ = INIT; - len = strlen(user); - p += krb_put_int (len, p, sizeof(msg) - 1, 4); - memcpy(p, user, len); + len = strlen(kc->user); + p += KRB_PUT_INT (len, p, sizeof(msg) - 1, 4); + memcpy(p, kc->user, len); p += len; - *p++ = PASSIVE | (keepalivep ? KEEP_ALIVE : 0); - if (write_encrypted (otherside, msg, p - msg, schedule, - &key, &me, &him) < 0) + *p++ = PASSIVE | (kc->keepalive_flag ? KEEP_ALIVE : 0); + if (kx_write (kc, otherside, msg, p - msg) != p - msg) err (1, "write to %s", host); - len = read_encrypted (otherside, msg, sizeof(msg), &ret, - schedule, &key, &him, &me); + len = kx_read (kc, otherside, msg, sizeof(msg)); if (len <= 0) errx (1, "error reading initial message from %s: " "this probably means it's using an old version.", host); - p = (u_char *)ret; + p = (u_char *)msg; if (*p == ERROR) { p++; p += krb_get_int (p, &tmp, 4, 0); @@ -269,18 +251,17 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, xauthfile[tmp] = '\0'; p += tmp; - status_output (debugp); + status_output (kc->debug_flag); for (;;) { pid_t child; - len = read_encrypted (otherside, msg, sizeof(msg), &ret, - schedule, &key, &him, &me); + len = kx_read (kc, otherside, msg, sizeof(msg)); if (len < 0) err (1, "read from %s", host); else if (len == 0) return 0; - p = (u_char *)ret; + p = (u_char *)msg; if (*p == ERROR) { p++; p += krb_get_int (p, &tmp, 4, 0); @@ -302,7 +283,7 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, int fd; int xserver; - addr = him; + addr = kc->thataddr; close (otherside); addr.sin_port = htons(tmp); @@ -318,7 +299,7 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, } #endif #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) - if (keepalivep) { + if (kc->keepalive_flag) { int one = 1; setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, @@ -343,7 +324,7 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, if (xserver < 0) return 1; } - return passive_session (xserver, fd, &key, schedule); + return passive_session (xserver, fd, kc); } else { } } @@ -354,31 +335,26 @@ doit_passive (char *host, char *user, int debugp, int keepalivep, */ static int -doit_active (char *host, char *user, - int debugpp, int keepalivep, int tcpp, int port) +doit_active (kx_context *kc) { - des_key_schedule schedule; - des_cblock key; int otherside; int nsockets; struct x_socket *sockets; - struct sockaddr_in me, him; u_char msg[1024], *p; - int len = strlen(user); - void *ret; + int len = strlen(kc->user); int tmp, tmp2; char *s; int i; size_t rem; u_int32_t other_port; int error; + char *host = kc->host; - otherside = connect_host (host, user, &key, schedule, port, - &me, &him); + otherside = connect_host (kc); if (otherside < 0) return 1; #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) - if (keepalivep) { + if (kc->keepalive_flag) { int one = 1; setsockopt (otherside, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, @@ -389,23 +365,23 @@ doit_active (char *host, char *user, rem = sizeof(msg); *p++ = INIT; --rem; - len = strlen(user); - tmp = krb_put_int (len, p, rem, 4); + len = strlen(kc->user); + tmp = KRB_PUT_INT (len, p, rem, 4); if (tmp < 0) return 1; p += tmp; rem -= tmp; - memcpy(p, user, len); + memcpy(p, kc->user, len); p += len; rem -= len; - *p++ = (keepalivep ? KEEP_ALIVE : 0); + *p++ = (kc->keepalive_flag ? KEEP_ALIVE : 0); --rem; s = getenv("DISPLAY"); if (s == NULL || (s = strchr(s, ':')) == NULL) s = ":0"; len = strlen (s); - tmp = krb_put_int (len, p, rem, 4); + tmp = KRB_PUT_INT (len, p, rem, 4); if (tmp < 0) return 1; rem -= tmp; @@ -418,7 +394,7 @@ doit_active (char *host, char *user, if (s == NULL) s = ""; len = strlen (s); - tmp = krb_put_int (len, p, rem, 4); + tmp = KRB_PUT_INT (len, p, rem, 4); if (tmp < 0) return 1; p += len; @@ -427,15 +403,13 @@ doit_active (char *host, char *user, p += len; rem -= len; - if (write_encrypted (otherside, msg, p - msg, schedule, - &key, &me, &him) < 0) + if (kx_write (kc, otherside, msg, p - msg) != p - msg) err (1, "write to %s", host); - len = read_encrypted (otherside, msg, sizeof(msg), &ret, - schedule, &key, &him, &me); + len = kx_read (kc, otherside, msg, sizeof(msg)); if (len < 0) err (1, "read from %s", host); - p = (u_char *)ret; + p = (u_char *)msg; if (*p == ERROR) { u_int32_t u32; @@ -447,11 +421,11 @@ doit_active (char *host, char *user, } else p++; - tmp2 = get_xsockets (&nsockets, &sockets, tcpp); + tmp2 = get_xsockets (&nsockets, &sockets, kc->tcp_flag); if (tmp2 < 0) return 1; display_num = tmp2; - if (tcpp) + if (kc->tcp_flag) snprintf (display, display_size, "localhost:%u", display_num); else snprintf (display, display_size, ":%u", display_num); @@ -461,7 +435,7 @@ doit_active (char *host, char *user, warnx ("failed creating cookie file: %s", strerror(error)); return 1; } - status_output (debugpp); + status_output (kc->debug_flag); for (;;) { fd_set fdset; pid_t child; @@ -488,14 +462,12 @@ doit_active (char *host, char *user, p = msg; *p++ = NEW_CONN; - if (write_encrypted (otherside, msg, p - msg, schedule, - &key, &me, &him) < 0) + if (kx_write (kc, otherside, msg, p - msg) != p - msg) err (1, "write to %s", host); - len = read_encrypted (otherside, msg, sizeof(msg), &ret, - schedule, &key, &him, &me); + len = kx_read (kc, otherside, msg, sizeof(msg)); if (len < 0) err (1, "read from %s", host); - p = (u_char *)ret; + p = (u_char *)msg; if (*p == ERROR) { u_int32_t val; @@ -521,7 +493,7 @@ doit_active (char *host, char *user, for (i = 0; i < nsockets; ++i) close (sockets[i].fd); - addr = him; + addr = kc->thataddr; close (otherside); addr.sin_port = htons(other_port); @@ -537,7 +509,7 @@ doit_active (char *host, char *user, } #endif #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) - if (keepalivep) { + if (kc->keepalive_flag) { int one = 1; setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, @@ -548,7 +520,7 @@ doit_active (char *host, char *user, if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) < 0) err(1, "connect"); - return active_session (fd, s, &key, schedule); + return active_session (fd, s, kc); } else { close (fd); } @@ -573,79 +545,212 @@ check_for_passive (const char *disp) || strncmp(disp, local_hostname, strlen(local_hostname)) == 0); } -static void -usage(void) +static int +doit (kx_context *kc, int passive_flag) { - fprintf(stderr, "Usage: %s [-p port] [-d] [-D] [-t] [-l remoteuser] host\n", - __progname); - exit (1); + signal (SIGCHLD, childhandler); + signal (SIGUSR1, usr1handler); + signal (SIGUSR2, usr2handler); + if (passive_flag) + return doit_passive (kc); + else + return doit_active (kc); +} + +#ifdef KRB4 +static int +doit_v4 (char *host, int port, char *user, + int passive_flag, int debug_flag, int keepalive_flag, int tcp_flag) +{ + int ret; + kx_context context; + + krb4_make_context (&context); + context_set (&context, + host, user, port, debug_flag, keepalive_flag, tcp_flag); + + ret = doit (&context, passive_flag); + context_destroy (&context); + return ret; +} +#endif /* KRB4 */ + +#ifdef KRB5 + +static int +doit_v5 (char *host, int port, char *user, + int passive_flag, int debug_flag, int keepalive_flag, int tcp_flag) +{ + int ret; + kx_context context; + + krb5_make_context (&context); + context_set (&context, + host, user, port, debug_flag, keepalive_flag, tcp_flag); + + ret = doit (&context, passive_flag); + context_destroy (&context); + return ret; +} + +#endif + +/* + * + */ + +#ifdef KRB4 +static int use_v4 = 0; +static int krb_debug_flag = 0; +#endif +#ifdef KRB5 +static int use_v5 = 0; +static int forward_flag = 0; +static int forwardable_flag = 0; +#endif +static char *port_str = NULL; +static char *user = NULL; +static int tcp_flag = 0; +static int passive_flag = 0; +static int keepalive_flag = 1; +static int debug_flag = 0; +static int version_flag = 0; +static int help_flag = 0; + +struct getargs args[] = { +#ifdef KRB4 + { "krb4", '4', arg_flag, &use_v4, "Use Kerberos V4", + NULL }, + { "krb4-debug", 'D', arg_flag, &krb_debug_flag, + "enable krb4 debugging" }, +#endif +#ifdef KRB5 + { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5", + NULL }, + { "forward", 'f', arg_flag, &forward_flag, "Forward credentials", + NULL }, + { "forwardable", 'F', arg_flag, &forwardable_flag, + "Forward forwardable credentials", NULL }, +#endif + { "port", 'p', arg_string, &port_str, "Use this port", + "number-of-service" }, + { "user", 'l', arg_string, &user, "Run as this user", + NULL }, + { "tcp", 't', arg_flag, &tcp_flag, + "Use a TCP connection for X11" }, + { "passive", 'P', arg_flag, &passive_flag, + "Force a passive connection" }, + { "keepalive", 'k', arg_negative_flag, &keepalive_flag, + "disable keep-alives" }, + { "debug", 'd', arg_flag, &debug_flag, + "Enable debug information" }, + { "version", 0, arg_flag, &version_flag, "Print version", + NULL }, + { "help", 0, arg_flag, &help_flag, NULL, + NULL } +}; + +static void +usage(int ret) +{ + arg_printusage (args, + sizeof(args) / sizeof(args[0]), + NULL, + "host"); + exit (ret); } /* * kx - forward x connection over a kerberos-encrypted channel. - * */ int main(int argc, char **argv) { - int force_passive = 0; - int keepalivep = 1; - char *user = NULL; - int debugp = 0, tcpp = 0; - int c; - int port = 0; + int port = 0; + int optind = 0; + int ret = 1; + char *host = NULL; - set_progname (argv[0]); - while((c = getopt(argc, argv, "ktdDl:p:P")) != EOF) { - switch(c) { - case 'd' : - debugp = 1; - break; - case 'D': - krb_enable_debug(); - break; - case 'k': - keepalivep = 0; - break; - case 't' : - tcpp = 1; - break; - case 'l' : - user = optarg; - break; - case 'p' : - port = htons(atoi (optarg)); - break; - case 'P' : - force_passive = 1; - break; - case '?': - default: - usage(); - } - } + set_progname (argv[0]); - argc -= optind; - argv += optind; + if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, + &optind)) + usage (1); - if (argc != 1) - usage (); - if (user == NULL) { - struct passwd *p = k_getpwuid (getuid ()); - if (p == NULL) - errx(1, "Who are you?"); - user = strdup (p->pw_name); - if (user == NULL) - errx (1, "strdup: out of memory"); - } - if (port == 0) - port = k_getportbyname ("kx", "tcp", htons(KX_PORT)); - signal (SIGCHLD, childhandler); - signal (SIGUSR1, usr1handler); - signal (SIGUSR2, usr2handler); - if (force_passive || check_for_passive(getenv("DISPLAY"))) - return doit_passive (argv[0], user, debugp, keepalivep, port); - else - return doit_active (argv[0], user, debugp, keepalivep, tcpp, port); + if (help_flag) + usage (0); + + if (version_flag) { + print_version (NULL); + return 0; + } + + if (optind != argc - 1) + usage (1); + + if (forwardable_flag) + forward_flag = 1; + + host = argv[optind]; + + if (port_str) { + struct servent *s = roken_getservbyname (port_str, "tcp"); + + if (s) + port = s->s_port; + else { + char *ptr; + + port = strtol (port_str, &ptr, 10); + if (port == 0 && ptr == port_str) + errx (1, "Bad port `%s'", port_str); + port = htons(port); + } + } + + if (user == NULL) { + struct passwd *pwd = getpwuid (getuid ()); + + if (pwd == NULL) + errx (1, "who are you?"); + user = pwd->pw_name; + } + + if (!passive_flag) + passive_flag = check_for_passive (getenv("DISPLAY")); + +#ifdef KRB4 + if (krb_debug_flag) + krb_enable_debug (); +#endif + +#if defined(KRB5) +#if defined(KRB4) + if (use_v4 == 0 && use_v5 == 0) + use_v5 = 1; +#else + use_v5 = 1; +#endif /* KRB4 */ +#elif defined(KRB4) + use_v4 = 1; +#endif + +#ifdef KRB5 + if (ret && use_v5) { + if (port == 0) + port = krb5_getportbyname(NULL, "kx", "tcp", htons(KX_PORT)); + ret = doit_v5 (host, port, user, + passive_flag, debug_flag, keepalive_flag, tcp_flag); + } +#endif +#ifdef KRB4 + if (ret && use_v4) { + if (port == 0) + port = k_getportbyname("kx", "tcp", htons(KX_PORT)); + ret = doit_v4 (host, port, user, + passive_flag, debug_flag, keepalive_flag, tcp_flag); + } +#endif + return ret; } diff --git a/appl/kx/kxd.c b/appl/kx/kxd.c index 71e2bcde9..3869aa4be 100644 --- a/appl/kx/kxd.c +++ b/appl/kx/kxd.c @@ -57,20 +57,8 @@ childhandler (int sig) SIGRETURN(0); } -static void -fatal(int, des_cblock *, des_key_schedule, - struct sockaddr_in *, struct sockaddr_in *, - char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format (printf, 6, 7))) -#endif -; - -static void -fatal (int fd, des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *thisaddr, - struct sockaddr_in *thataddr, - char *format, ...) +void +fatal (kx_context *kc, int fd, char *format, ...) { u_char msg[1024]; u_char *p; @@ -83,9 +71,9 @@ fatal (int fd, des_cblock *key, des_key_schedule schedule, vsnprintf (p + 4, sizeof(msg) - 5, format, args); syslog (LOG_ERR, p + 4); len = strlen (p + 4); - p += krb_put_int (len, p, 4, 4); + p += KRB_PUT_INT (len, p, 4, 4); p += len; - write_encrypted (fd, msg, p - msg, schedule, key, thisaddr, thataddr); + kx_write (kc, fd, msg, p - msg); va_end(args); exit (1); } @@ -105,80 +93,68 @@ cleanup(int nsockets, struct x_socket *sockets) } } -static int -recv_conn (int sock, des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *thisaddr, - struct sockaddr_in *thataddr, - int *dispnr, - int *nsockets, - struct x_socket **sockets, - int tcpp) -{ - int status; - KTEXT_ST ticket; - AUTH_DAT auth; - char user[ANAME_SZ]; - char instance[INST_SZ]; - int addrlen; - char version[KRB_SENDAUTH_VLEN + 1]; - struct passwd *passwd; - char remotehost[MaxHostNameLen]; - void *ret; - int len; - u_char msg[1024], *p; - u_int32_t tmp32; - int tmp; - int flags; +/* + * + */ - addrlen = sizeof(*thisaddr); - if (getsockname (sock, (struct sockaddr *)thisaddr, &addrlen) < 0 || - addrlen != sizeof(*thisaddr)) { +static int +recv_conn (int sock, kx_context *kc, + int *dispnr, int *nsockets, struct x_socket **sockets, + int tcp_flag) +{ + u_char msg[1024], *p; + char user[256]; + int addrlen; + struct passwd *passwd; + struct sockaddr_in thisaddr, thataddr; + char remotehost[MaxHostNameLen]; + int ret = 1; + int flags; + int len; + u_int32_t tmp32; + + addrlen = sizeof(thisaddr); + if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) { syslog (LOG_ERR, "getsockname: %m"); exit (1); } - addrlen = sizeof(*thataddr); - if (getpeername (sock, (struct sockaddr *)thataddr, &addrlen) < 0 || - addrlen != sizeof(*thataddr)) { + addrlen = sizeof(thataddr); + if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 || + addrlen != sizeof(thataddr)) { syslog (LOG_ERR, "getpeername: %m"); exit (1); } - inaddr2str (thataddr->sin_addr, remotehost, sizeof(remotehost)); + kc->thisaddr = thisaddr; + kc->thataddr = thataddr; - k_getsockinst (sock, instance, sizeof(instance)); - status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance, - thataddr, thisaddr, &auth, "", schedule, - version); - if (status != KSUCCESS) { - syslog (LOG_ERR, "krb_recvauth: %s", - krb_get_err_text(status)); - exit(1); + inaddr2str (thataddr.sin_addr, remotehost, sizeof(remotehost)); + + if (net_read (sock, msg, 4) != 4) { + syslog (LOG_ERR, "read: %m"); + exit (1); } - if( strncmp(version, KX_VERSION, KRB_SENDAUTH_VLEN) != 0) { - /* Try to be nice to old kx's */ - if (strncmp (version, KX_OLD_VERSION, KRB_SENDAUTH_VLEN) == 0) { - char *old_errmsg = "\001Old version of kx. Please upgrade."; - syslog (LOG_ERR, "Old version client (%s)", version); - - krb_net_read (sock, user, sizeof(user)); - krb_net_write (sock, old_errmsg, strlen(old_errmsg) + 1); - exit (1); - } - - fatal(sock, key, schedule, thisaddr, thataddr, - "Bad version %s", version); +#ifdef KRB5 + if (ret && recv_v5_auth (kc, sock, msg) == 0) + ret = 0; +#endif +#ifdef KRB4 + if (ret && recv_v4_auth (kc, sock, msg) == 0) + ret = 0; +#endif + if (ret) { + syslog (LOG_ERR, "unrecognized auth protocol: %x %x %x %x"); + return 1; } - memcpy(key, &auth.session, sizeof(des_cblock)); - len = read_encrypted (sock, msg, sizeof(msg), &ret, - schedule, key, thataddr, thisaddr); + len = kx_read (kc, sock, msg, sizeof(msg)); if (len < 0) return 1; - p = (u_char *)ret; + p = (u_char *)msg; if (*p != INIT) - fatal(sock, key, schedule, thisaddr, thataddr, - "Bad message"); + fatal(kc, sock, "Bad message"); p++; p += krb_get_int (p, &tmp32, 4, 0); len = min(sizeof(user), tmp32); @@ -188,25 +164,21 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, passwd = k_getpwnam (user); if (passwd == NULL) - fatal (sock, key, schedule, thisaddr, thataddr, - "Cannot find uid"); - if (kuserok(&auth, user) != 0) - fatal (sock, key, schedule, thisaddr, thataddr, - "%s is not allowed to login as %s", - krb_unparse_name_long (auth.pname, - auth.pinst, - auth.prealm), - user); + fatal (kc, sock, "cannot find uid for %s", user); + + if (context_userok (kc, user) != 0) + fatal (kc, sock, "%s not allowed to login as %s", + kc->user, user); flags = *p++; if (flags & PASSIVE) { pid_t pid; + int tmp; - tmp = get_xsockets (nsockets, sockets, tcpp); + tmp = get_xsockets (nsockets, sockets, tcp_flag); if (tmp < 0) { - fatal (sock, key, schedule, thisaddr, thataddr, - "Cannot create X socket(s): %s", + fatal (kc, sock, "Cannot create X socket(s): %s", strerror(errno)); } *dispnr = tmp; @@ -214,16 +186,14 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, if (chown_xsockets (*nsockets, *sockets, passwd->pw_uid, passwd->pw_gid)) { cleanup (*nsockets, *sockets); - fatal (sock, key, schedule, thisaddr, thataddr, - "Cannot chown sockets: %s", + fatal (kc, sock, "Cannot chown sockets: %s", strerror(errno)); } pid = fork(); if (pid == -1) { cleanup (*nsockets, *sockets); - fatal (sock, key, schedule, thisaddr, thataddr, - "fork: %s", strerror(errno)); + fatal (kc, sock, "fork: %s", strerror(errno)); } else if (pid != 0) { int status; @@ -239,14 +209,12 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, if (setgid (passwd->pw_gid) || initgroups(passwd->pw_name, passwd->pw_gid) || setuid(passwd->pw_uid)) { - fatal (sock, key, schedule, thisaddr, thataddr, - "Cannot set uid"); + fatal (kc, sock, "cannot set uid"); } syslog (LOG_INFO, "from %s(%s): %s -> %s", remotehost, - inet_ntoa(thataddr->sin_addr), - krb_unparse_name_long (auth.pname, auth.pinst, auth.prealm), - user); + inet_ntoa(thataddr.sin_addr), + kc->user); umask(077); if (!(flags & PASSIVE)) { p += krb_get_int (p, &tmp32, 4, 0); @@ -276,35 +244,32 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, */ static int -passive_session (int fd, int sock, int cookiesp, des_cblock *key, - des_key_schedule schedule) +passive_session (kx_context *kc, int fd, int sock, int cookiesp) { if (verify_and_remove_cookies (fd, sock, cookiesp)) return 1; else - return copy_encrypted (fd, sock, key, schedule); + return copy_encrypted (kc, fd, sock); } static int -active_session (int fd, int sock, int cookiesp, des_cblock *key, - des_key_schedule schedule) +active_session (kx_context *kc, int fd, int sock, int cookiesp) { fd = connect_local_xsocket(0); if (replace_cookie (fd, sock, xauthfile, cookiesp)) return 1; else - return copy_encrypted (fd, sock, key, schedule); + return copy_encrypted (kc, fd, sock); } static int -doit_conn (int fd, int meta_sock, int flags, int cookiesp, - des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *thisaddr, - struct sockaddr_in *thataddr) +doit_conn (kx_context *kc, + int fd, int meta_sock, int flags, int cookiesp) { int sock, sock2; struct sockaddr_in addr; + struct sockaddr_in thisaddr; int addrlen; u_char msg[1024], *p; @@ -334,8 +299,7 @@ doit_conn (int fd, int meta_sock, int flags, int cookiesp, return 1; } addrlen = sizeof(addr); - if (getsockname (sock, (struct sockaddr *)&addr, - &addrlen) < 0) { + if (getsockname (sock, (struct sockaddr *)&addr, &addrlen) < 0) { syslog (LOG_ERR, "getsockname: %m"); return 1; } @@ -345,15 +309,15 @@ doit_conn (int fd, int meta_sock, int flags, int cookiesp, } p = msg; *p++ = NEW_CONN; - p += krb_put_int (ntohs(addr.sin_port), p, 4, 4); + p += KRB_PUT_INT (ntohs(addr.sin_port), p, 4, 4); - if (write_encrypted (meta_sock, msg, p - msg, schedule, key, - thisaddr, thataddr) < 0) { + if (kx_write (kc, meta_sock, msg, p - msg) < 0) { syslog (LOG_ERR, "write: %m"); return 1; } - sock2 = accept (sock, (struct sockaddr *)thisaddr, &addrlen); + addrlen = sizeof(thisaddr); + sock2 = accept (sock, (struct sockaddr *)&thisaddr, &addrlen); if (sock2 < 0) { syslog (LOG_ERR, "accept: %m"); return 1; @@ -362,9 +326,9 @@ doit_conn (int fd, int meta_sock, int flags, int cookiesp, close (meta_sock); if (flags & PASSIVE) - return passive_session (fd, sock2, cookiesp, key, schedule); + return passive_session (kc, fd, sock2, cookiesp); else - return active_session (fd, sock2, cookiesp, key, schedule); + return active_session (kc, fd, sock2, cookiesp); } /* @@ -372,18 +336,14 @@ doit_conn (int fd, int meta_sock, int flags, int cookiesp, */ static void -check_user_console (int fd, des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *thisaddr, - struct sockaddr_in *thataddr) +check_user_console (kx_context *kc, int fd) { struct stat sb; if (stat ("/dev/console", &sb) < 0) - fatal (fd, key, schedule, thisaddr, thataddr, - "Cannot stat /dev/console"); + fatal (kc, fd, "Cannot stat /dev/console: %s", strerror(errno)); if (getuid() != sb.st_uid) - fatal (fd, key, schedule, thisaddr, thataddr, - "Permission denied"); + fatal (kc, fd, "Permission denied"); } /* @@ -391,10 +351,13 @@ check_user_console (int fd, des_cblock *key, des_key_schedule schedule, */ static int -doit_passive (int sock, des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *me, struct sockaddr_in *him, int flags, - int displaynr, int nsockets, struct x_socket *sockets, - int tcpp) +doit_passive (kx_context *kc, + int sock, + int flags, + int dispnr, + int nsockets, + struct x_socket *sockets, + int tcp_flag) { int tmp; int len; @@ -402,8 +365,8 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, u_char msg[1024], *p; int error; - display_num = displaynr; - if (tcpp) + display_num = dispnr; + if (tcp_flag) snprintf (display, display_size, "localhost:%u", display_num); else snprintf (display, display_size, ":%u", display_num); @@ -411,9 +374,7 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, cookie, cookie_len); if (error) { cleanup(nsockets, sockets); - fatal (sock, key, schedule, me, him, - "Cookie-creation failed with: %s", - strerror(error)); + fatal (kc, sock, "Cookie-creation failed: %s", strerror(error)); return 1; } @@ -423,7 +384,7 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, --rem; len = strlen (display); - tmp = krb_put_int (len, p, rem, 4); + tmp = KRB_PUT_INT (len, p, rem, 4); if (tmp < 0 || rem < len + 4) { syslog (LOG_ERR, "doit: buffer too small"); cleanup(nsockets, sockets); @@ -437,7 +398,7 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, rem -= len; len = strlen (xauthfile); - tmp = krb_put_int (len, p, rem, 4); + tmp = KRB_PUT_INT (len, p, rem, 4); if (tmp < 0 || rem < len + 4) { syslog (LOG_ERR, "doit: buffer too small"); cleanup(nsockets, sockets); @@ -450,8 +411,7 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, p += len; rem -= len; - if(write_encrypted (sock, msg, p - msg, schedule, key, - me, him) < 0) { + if(kx_write (kc, sock, msg, p - msg) < 0) { syslog (LOG_ERR, "write: %m"); cleanup(nsockets, sockets); return 1; @@ -550,8 +510,7 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, } else if (child == 0) { for (i = 0; i < nsockets; ++i) close (sockets[i].fd); - return doit_conn (fd, sock, flags, cookiesp, - key, schedule, me, him); + return doit_conn (kc, fd, sock, flags, cookiesp); } else { close (fd); } @@ -563,35 +522,32 @@ doit_passive (int sock, des_cblock *key, des_key_schedule schedule, */ static int -doit_active (int sock, des_cblock *key, des_key_schedule schedule, - struct sockaddr_in *me, struct sockaddr_in *him, - int flags, int tcpp) +doit_active (kx_context *kc, + int sock, + int flags, + int tcp_flag) { u_char msg[1024], *p; - check_user_console (sock, key, schedule, me, him); + check_user_console (kc, sock); p = msg; *p++ = ACK; - if(write_encrypted (sock, msg, p - msg, schedule, key, - me, him) < 0) { + if(kx_write (kc, sock, msg, p - msg) < 0) { syslog (LOG_ERR, "write: %m"); return 1; } for (;;) { pid_t child; int len; - void *ret; - len = read_encrypted (sock, msg, sizeof(msg), &ret, - schedule, key, - him, me); + len = kx_read (kc, sock, msg, sizeof(msg)); if (len < 0) { syslog (LOG_ERR, "read: %m"); return 1; } - p = (u_char *)ret; + p = (u_char *)msg; if (*p != NEW_CONN) { syslog (LOG_ERR, "bad_message: %d", *p); return 1; @@ -602,8 +558,7 @@ doit_active (int sock, des_cblock *key, des_key_schedule schedule, syslog (LOG_ERR, "fork: %m"); return 1; } else if (child == 0) { - return doit_conn (sock, sock, flags, 1, - key, schedule, me, him); + return doit_conn (kc, sock, sock, flags, 1); } else { } } @@ -614,31 +569,49 @@ doit_active (int sock, des_cblock *key, des_key_schedule schedule, */ static int -doit(int sock, int tcpp) +doit(int sock, int tcp_flag) { - des_key_schedule schedule; - des_cblock key; - struct sockaddr_in me, him; - int flags; - struct x_socket *sockets; - int nsockets; - int dispnr; + int ret; + kx_context context; + int dispnr; + int nsockets; + struct x_socket *sockets; + int flags; - flags = recv_conn (sock, &key, schedule, &me, &him, - &dispnr, &nsockets, &sockets, tcpp); + flags = recv_conn (sock, &context, &dispnr, &nsockets, &sockets, tcp_flag); - if (flags & PASSIVE) - return doit_passive (sock, &key, schedule, &me, &him, flags, - dispnr, nsockets, sockets, tcpp); - else - return doit_active (sock, &key, schedule, &me, &him, flags, tcpp); + if (flags & PASSIVE) + ret = doit_passive (&context, sock, flags, dispnr, + nsockets, sockets, tcp_flag); + else + ret = doit_active (&context, sock, flags, tcp_flag); + context_destroy (&context); + return ret; } +static char *port_str = NULL; +static int inetd_flag = 0; +static int tcp_flag = 0; +static int version_flag = 0; +static int help_flag = 0; + +struct getargs args[] = { + { "inetd", 'i', arg_negative_flag, &inetd_flag, + "Not started from inetd" }, + { "port", 'p', arg_string, &port_str, "Use this port", + "port" }, + { "version", 0, arg_flag, &version_flag }, + { "help", 0, arg_flag, &help_flag } +}; + static void -usage (void) +usage(int ret) { - fprintf (stderr, "Usage: %s [-i] [-t] [-p port]\n", __progname); - exit (1); + arg_printusage (args, + sizeof(args) / sizeof(args[0]), + NULL, + "host"); + exit (ret); } /* @@ -648,34 +621,50 @@ usage (void) int main (int argc, char **argv) { - int c; - int no_inetd = 0; - int tcpp = 0; - int port = 0; + int port; + int optind = 0; - set_progname (argv[0]); + set_progname (argv[0]); + roken_openlog ("kxd", LOG_ODELAY | LOG_PID, LOG_DAEMON); - while( (c = getopt (argc, argv, "itp:")) != EOF) { - switch (c) { - case 'i': - no_inetd = 1; - break; - case 't': - tcpp = 1; - break; - case 'p': - port = htons(atoi (optarg)); - break; - case '?': - default: - usage (); - } - } + if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, + &optind)) + usage (1); + + if (help_flag) + usage (0); + + if (version_flag) { + print_version (NULL); + return 0; + } + + if(port_str) { + struct servent *s = roken_getservbyname (port_str, "tcp"); + + if (s) + port = s->s_port; + else { + char *ptr; + + port = strtol (port_str, &ptr, 10); + if (port == 0 && ptr == port_str) + errx (1, "bad port `%s'", port_str); + port = htons(port); + } + } else { +#if defined(KRB5) + port = krb5_getportbyname(NULL, "kx", "tcp", htons(KX_PORT)); +#elif defined(KRB4) + port = k_getportbyname ("kx", "tcp", htons(KX_PORT)); +#else +#error define KRB4 or KRB5 +#endif + } + + if (!inetd_flag) + mini_inetd (port); - if (no_inetd) - mini_inetd (port ? port : k_getportbyname("kx", "tcp", - htons(KX_PORT))); - roken_openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON); signal (SIGCHLD, childhandler); - return doit(STDIN_FILENO, tcpp); + return doit(STDIN_FILENO, tcp_flag); }