diff -Naur --exclude=autom4te.cache openssh-4.3p2/auth2.c openssh-4.3p2-gssapi/auth2.c --- openssh-4.3p2/auth2.c 2005-09-23 21:43:51.000000000 -0500 +++ openssh-4.3p2-gssapi/auth2.c 2006-07-26 15:17:38.000000000 -0500 @@ -55,14 +55,20 @@ extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI +extern Authmethod method_external; +extern Authmethod method_gsskeyex; extern Authmethod method_gssapi; +extern Authmethod method_gssapi_compat; #endif Authmethod *authmethods[] = { &method_none, &method_pubkey, #ifdef GSSAPI + &method_gsskeyex, + &method_external, &method_gssapi, + &method_gssapi_compat, #endif &method_passwd, &method_kbdint, @@ -143,14 +149,54 @@ user = packet_get_string(NULL); service = packet_get_string(NULL); method = packet_get_string(NULL); - debug("userauth-request for user %s service %s method %s", user, service, method); + +#ifdef GSSAPI + if (user[0] == '\0') { + debug("received empty username for %s", method); + if (strcmp(method, "external-keyx") == 0 || + strcmp(method, "gssapi-keyex") == 0) { + char *lname = NULL; + PRIVSEP(ssh_gssapi_localname(&lname)); + if (lname && lname[0] != '\0') { + xfree(user); + user = lname; + debug("set username to %s from gssapi context", user); + } else { + debug("failed to set username from gssapi context"); + packet_send_debug("failed to set username from gssapi context"); + } + } + } +#endif + + debug("userauth-request for user %s service %s method %s", + user[0] ? user : "", service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); if ((style = strchr(user, ':')) != NULL) *style++ = 0; - if (authctxt->attempt++ == 0) { - /* setup auth context */ + /* If first time or username changed or implicit username, + setup/reset authentication context. */ + if ((authctxt->attempt++ == 0) || + (strcmp(user, authctxt->user) != 0) || + (strcmp(user, "") == 0)) { + if (authctxt->user) { + xfree(authctxt->user); + authctxt->user = NULL; + } + authctxt->valid = 0; +#ifdef GSSAPI + /* If we're going to set the username based on the + GSSAPI context later, then wait until then to + verify it. Just put in placeholders for now. */ + if ((strcmp(user, "") == 0) && + ((strcmp(method, "gssapi") == 0) || + (strcmp(method, "gssapi-with-mic") == 0))) { + authctxt->pw = fakepw(); + authctxt->user = xstrdup(user); + } else { +#endif authctxt->pw = PRIVSEP(getpwnamallow(user)); authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { @@ -163,19 +209,28 @@ PRIVSEP(audit_event(SSH_INVALID_USER)); #endif } +#ifdef GSSAPI + } /* endif for setting username based on GSSAPI context */ +#endif #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(authctxt)); #endif setproctitle("%s%s", authctxt->valid ? user : "unknown", use_privsep ? " [net]" : ""); +#ifdef GSSAPI + if (authctxt->attempt == 1) { +#endif authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; if (use_privsep) mm_inform_authserv(service, style); - } else if (strcmp(user, authctxt->user) != 0 || - strcmp(service, authctxt->service) != 0) { - packet_disconnect("Change of username or service not allowed: " +#ifdef GSSAPI + } /* if (authctxt->attempt == 1) */ +#endif + } + if (strcmp(service, authctxt->service) != 0) { + packet_disconnect("Change of service not allowed: " "(%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } @@ -188,6 +243,7 @@ #endif authctxt->postponed = 0; + authctxt->server_caused_failure = 0; /* try to authenticate user */ m = authmethod_lookup(method); @@ -258,7 +314,9 @@ /* now we can break out */ authctxt->success = 1; } else { - if (authctxt->failures++ > options.max_authtries) { + /* Dont count server configuration issues against the client */ + if (!authctxt->server_caused_failure && + authctxt->failures++ > options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif diff -Naur --exclude=autom4te.cache openssh-4.3p2/auth2-gss.c openssh-4.3p2-gssapi/auth2-gss.c --- openssh-4.3p2/auth2-gss.c 2005-11-04 22:07:05.000000000 -0600 +++ openssh-4.3p2-gssapi/auth2-gss.c 2006-07-26 15:17:38.000000000 -0500 @@ -41,11 +41,72 @@ extern ServerOptions options; +static void ssh_gssapi_userauth_error(Gssctxt *ctxt); static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); static void input_gssapi_errtok(int, u_int32_t, void *); +static int gssapi_with_mic = 1; /* flag to toggle "gssapi-with-mic" vs. + "gssapi" */ + +static int +userauth_external(Authctxt *authctxt) +{ + packet_check_eom(); + + if (authctxt->valid && authctxt->user && authctxt->user[0]) { + return(PRIVSEP(ssh_gssapi_userok(authctxt->user))); + } + return 0; +} + +/* + * The 'gssapi_keyex' userauth mechanism. + */ +static int +userauth_gsskeyex(Authctxt *authctxt) +{ + int authenticated = 0; + Buffer b, b2; + gss_buffer_desc mic, gssbuf, gssbuf2; + u_int len; + + mic.value = packet_get_string(&len); + mic.length = len; + + packet_check_eom(); + + ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, + "gssapi-keyex"); + + gssbuf.value = buffer_ptr(&b); + gssbuf.length = buffer_len(&b); + + /* client may have used empty username to determine target + name from GSSAPI context */ + ssh_gssapi_buildmic(&b2, "", authctxt->service, "gssapi-keyex"); + + gssbuf2.value = buffer_ptr(&b2); + gssbuf2.length = buffer_len(&b2); + + /* gss_kex_context is NULL with privsep, so we can't check it here */ + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, + &gssbuf, &mic))) || + !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, + &gssbuf2, &mic)))) { + if (authctxt->valid && authctxt->user && authctxt->user[0]) { + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + } + } + + buffer_free(&b); + buffer_free(&b2); + xfree(mic.value); + + return (authenticated); +} + /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) @@ -62,7 +123,10 @@ u_int len; u_char *doid = NULL; - if (!authctxt->valid || authctxt->user == NULL) + /* authctxt->valid may be 0 if we haven't yet determined + username from gssapi context. */ + + if (authctxt->user == NULL) return (0); mechs = packet_get_int(); @@ -96,11 +160,13 @@ if (!present) { xfree(doid); + authctxt->server_caused_failure = 1; return (0); } if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { xfree(doid); + authctxt->server_caused_failure = 1; return (0); } @@ -128,7 +194,7 @@ Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; - OM_uint32 maj_status, min_status, flags; + OM_uint32 maj_status, min_status, flags=0; u_int len; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) @@ -146,6 +212,7 @@ xfree(recv_tok.value); if (GSS_ERROR(maj_status)) { + ssh_gssapi_userauth_error(gssctxt); if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); packet_put_string(send_tok.value, send_tok.length); @@ -153,7 +220,9 @@ } authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, 0, "gssapi-with-mic"); + userauth_finish(authctxt, 0, + gssapi_with_mic ? "gssapi-with-mic" : + "gssapi"); } else { if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); @@ -162,7 +231,7 @@ } if (maj_status == GSS_S_COMPLETE) { dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - if (flags & GSS_C_INTEG_FLAG) + if (flags & GSS_C_INTEG_FLAG && gssapi_with_mic) dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, &input_gssapi_mic); else @@ -209,6 +278,33 @@ gss_release_buffer(&maj_status, &send_tok); } +static void +gssapi_set_implicit_username(Authctxt *authctxt) +{ + if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) { + char *lname = NULL; + PRIVSEP(ssh_gssapi_localname(&lname)); + if (lname && lname[0] != '\0') { + if (authctxt->user) xfree(authctxt->user); + authctxt->user = lname; + debug("set username to %s from gssapi context", lname); + authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user)); + if (authctxt->pw) { + authctxt->valid = 1; + } + } else { + debug("failed to set username from gssapi context"); + packet_send_debug("failed to set username from gssapi context"); + } + } + if (authctxt->pw) { +#ifdef USE_PAM + if (options.use_pam) + PRIVSEP(start_pam(authctxt)); +#endif + } +} + /* * This is called when the client thinks we've completed authentication. * It should only be enabled in the dispatch handler by the function above, @@ -225,6 +321,8 @@ if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); + gssapi_set_implicit_username(authctxt); + gssctxt = authctxt->methoddata; /* @@ -234,14 +332,34 @@ packet_check_eom(); - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + /* user should be set if valid but we double-check here */ + if (authctxt->valid && authctxt->user && authctxt->user[0]) { + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + } else { + authenticated = 0; + } authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic"); + userauth_finish(authctxt, authenticated, + gssapi_with_mic ? "gssapi-with-mic" : "gssapi"); +} + +static int +userauth_gssapi_with_mic(Authctxt *authctxt) +{ + gssapi_with_mic = 1; + return userauth_gssapi(authctxt); +} + +static int +userauth_gssapi_without_mic(Authctxt *authctxt) +{ + gssapi_with_mic = 0; + return userauth_gssapi(authctxt); } static void @@ -257,6 +375,8 @@ if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); + gssapi_set_implicit_username(authctxt); + gssctxt = authctxt->methoddata; mic.value = packet_get_string(&len); @@ -269,7 +389,11 @@ gssbuf.length = buffer_len(&b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) + if (authctxt->valid && authctxt->user && authctxt->user[0]) { authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + } else { + authenticated = 0; + } else logit("GSSAPI MIC check failed"); @@ -284,9 +408,44 @@ userauth_finish(authctxt, authenticated, "gssapi-with-mic"); } +static void ssh_gssapi_userauth_error(Gssctxt *ctxt) { + char *errstr; + OM_uint32 maj,min; + + errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min)); + if (errstr) { + packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR); + packet_put_int(maj); + packet_put_int(min); + packet_put_cstring(errstr); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); + xfree(errstr); + } +} + +Authmethod method_external = { + "external-keyx", + userauth_external, + &options.gss_authentication +}; + +Authmethod method_gsskeyex = { + "gssapi-keyex", + userauth_gsskeyex, + &options.gss_authentication +}; + Authmethod method_gssapi = { "gssapi-with-mic", - userauth_gssapi, + userauth_gssapi_with_mic, + &options.gss_authentication +}; + +Authmethod method_gssapi_compat = { + "gssapi", + userauth_gssapi_without_mic, &options.gss_authentication }; diff -Naur --exclude=autom4te.cache openssh-4.3p2/auth.c openssh-4.3p2-gssapi/auth.c --- openssh-4.3p2/auth.c 2005-08-31 11:59:49.000000000 -0500 +++ openssh-4.3p2-gssapi/auth.c 2006-07-26 15:17:38.000000000 -0500 @@ -247,7 +247,8 @@ authmsg, method, authctxt->valid ? "" : "invalid user ", - authctxt->user, + (authctxt->user && authctxt->user[0]) ? + authctxt->user : "", get_remote_ipaddr(), get_remote_port(), info); @@ -495,7 +496,8 @@ pw = getpwnam(user); if (pw == NULL) { logit("Invalid user %.100s from %.100s", - user, get_remote_ipaddr()); + (user && user[0]) ? user : "", + get_remote_ipaddr()); #ifdef CUSTOM_FAILED_LOGIN record_failed_login(user, get_canonical_hostname(options.use_dns), "ssh"); diff -Naur --exclude=autom4te.cache openssh-4.3p2/auth.h openssh-4.3p2-gssapi/auth.h --- openssh-4.3p2/auth.h 2005-07-06 20:50:20.000000000 -0500 +++ openssh-4.3p2-gssapi/auth.h 2006-07-26 15:17:38.000000000 -0500 @@ -42,6 +42,9 @@ #ifdef KRB5 #include #endif +#ifdef AFS_KRB5 +#include +#endif typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; @@ -53,6 +56,7 @@ int valid; /* user exists and is allowed to login */ int attempt; int failures; + int server_caused_failure; int force_pwchange; char *user; /* username sent by the client */ char *service; @@ -69,6 +73,9 @@ char *krb5_ticket_file; char *krb5_ccname; #endif +#ifdef SESSION_HOOKS + char *session_env_file; +#endif Buffer *loginmsg; void *methoddata; }; diff -Naur --exclude=autom4te.cache openssh-4.3p2/auth-krb5.c openssh-4.3p2-gssapi/auth-krb5.c --- openssh-4.3p2/auth-krb5.c 2005-11-22 02:42:42.000000000 -0600 +++ openssh-4.3p2-gssapi/auth-krb5.c 2006-07-26 15:17:38.000000000 -0500 @@ -156,8 +156,13 @@ len = strlen(authctxt->krb5_ticket_file) + 6; authctxt->krb5_ccname = xmalloc(len); +#ifdef USE_CCAPI + snprintf(authctxt->krb5_ccname, len, "API:%s", + authctxt->krb5_ticket_file); +#else snprintf(authctxt->krb5_ccname, len, "FILE:%s", authctxt->krb5_ticket_file); +#endif #ifdef USE_PAM if (options.use_pam) @@ -209,15 +214,22 @@ #ifndef HEIMDAL krb5_error_code ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { - int tmpfd, ret; + int ret; char ccname[40]; mode_t old_umask; +#ifdef USE_CCAPI + char cctemplate[] = "API:krb5cc_%d"; +#else + char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; + int tmpfd; +#endif ret = snprintf(ccname, sizeof(ccname), - "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); + cctemplate, geteuid()); if (ret < 0 || (size_t)ret >= sizeof(ccname)) return ENOMEM; +#ifndef USE_CCAPI old_umask = umask(0177); tmpfd = mkstemp(ccname + strlen("FILE:")); umask(old_umask); @@ -232,6 +244,7 @@ return errno; } close(tmpfd); +#endif return (krb5_cc_resolve(ctx, ccname, ccache)); } diff -Naur --exclude=autom4te.cache openssh-4.3p2/buffer.c openssh-4.3p2-gssapi/buffer.c --- openssh-4.3p2/buffer.c 2005-03-14 06:22:26.000000000 -0600 +++ openssh-4.3p2-gssapi/buffer.c 2006-07-26 15:17:38.000000000 -0500 @@ -107,7 +107,7 @@ /* Increase the size of the buffer and retry. */ newlen = buffer->alloc + len + 32768; - if (newlen > BUFFER_MAX_LEN) + if (newlen > BUFFER_MAX_HPN_LEN) fatal("buffer_append_space: alloc %u not supported", newlen); buffer->buf = xrealloc(buffer->buf, newlen); diff -Naur --exclude=autom4te.cache openssh-4.3p2/buffer.h openssh-4.3p2-gssapi/buffer.h --- openssh-4.3p2/buffer.h 2005-03-14 06:22:26.000000000 -0600 +++ openssh-4.3p2-gssapi/buffer.h 2006-07-26 15:17:38.000000000 -0500 @@ -23,8 +23,15 @@ u_int end; /* Offset of last byte containing data. */ } Buffer; -#define BUFFER_MAX_CHUNK 0x100000 -#define BUFFER_MAX_LEN 0xa00000 +#define BUFFER_MAX_CHUNK 0x100000 /*1MB*/ +#define BUFFER_MAX_LEN 0xa00000 /*10MB*/ + +/* this value for BUFFER_MAX_HPN_LEN is */ +/* still undersized for the faster networks */ +/* it might make sense to have yet another */ +/* MAX_LEN for 10+GB networks. Something closer to */ +/* 128MB or 192MB -cjr*/ +#define BUFFER_MAX_HPN_LEN 0x2000000 /*32MB*/ void buffer_init(Buffer *); void buffer_clear(Buffer *); diff -Naur --exclude=autom4te.cache openssh-4.3p2/canohost.c openssh-4.3p2-gssapi/canohost.c --- openssh-4.3p2/canohost.c 2005-12-30 23:19:54.000000000 -0600 +++ openssh-4.3p2-gssapi/canohost.c 2006-07-26 15:17:38.000000000 -0500 @@ -401,3 +401,33 @@ { return get_port(1); } + +void +resolve_localhost(char **host) +{ + struct hostent *hostinfo; + + hostinfo = gethostbyname(*host); + if (hostinfo == NULL || hostinfo->h_name == NULL) { + debug("gethostbyname(%s) failed", *host); + return; + } + if (hostinfo->h_addrtype == AF_INET) { + struct in_addr addr; + addr = *(struct in_addr *)(hostinfo->h_addr); + if (ntohl(addr.s_addr) == INADDR_LOOPBACK) { + char buf[MAXHOSTNAMELEN]; + if (gethostname(buf, sizeof(buf)) < 0) { + debug("gethostname() failed"); + return; + } + hostinfo = gethostbyname(buf); + xfree(*host); + if (hostinfo == NULL || hostinfo->h_name == NULL) { + *host = xstrdup(buf); + } else { + *host = xstrdup(hostinfo->h_name); + } + } + } +} diff -Naur --exclude=autom4te.cache openssh-4.3p2/canohost.h openssh-4.3p2-gssapi/canohost.h --- openssh-4.3p2/canohost.h 2005-02-02 06:30:25.000000000 -0600 +++ openssh-4.3p2-gssapi/canohost.h 2006-07-26 15:17:38.000000000 -0500 @@ -24,4 +24,6 @@ int get_remote_port(void); int get_local_port(void); +void resolve_localhost(char **host); + void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); diff -Naur --exclude=autom4te.cache openssh-4.3p2/channels.c openssh-4.3p2-gssapi/channels.c --- openssh-4.3p2/channels.c 2006-01-31 04:47:15.000000000 -0600 +++ openssh-4.3p2-gssapi/channels.c 2006-07-26 15:17:38.000000000 -0500 @@ -56,6 +56,7 @@ #include "pathnames.h" #include "bufaux.h" + /* -- channel core */ /* @@ -288,6 +289,7 @@ c->local_window_max = window; c->local_consumed = 0; c->local_maxpacket = maxpack; + c->dynamic_window = 0; c->remote_id = -1; c->remote_name = xstrdup(remote_name); c->remote_window = 0; @@ -744,13 +746,32 @@ FD_SET(c->sock, writeset); } +int channel_tcpwinsz () { + u_int32_t tcpwinsz = 0; + socklen_t optsz = sizeof(tcpwinsz); + int ret = -1; + if(!packet_connection_is_on_socket()) + return(131072); + ret = getsockopt(packet_get_connection_in(), + SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); + if ((ret == 0) && tcpwinsz > BUFFER_MAX_HPN_LEN) + tcpwinsz = BUFFER_MAX_HPN_LEN; + debug2("tcpwinsz: %d for connection: %d", tcpwinsz, packet_get_connection_in()); + return(tcpwinsz); +} + static void channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) { u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); /* check buffer limits */ - limit = MIN(limit, (BUFFER_MAX_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF)); + if (!c->tcpwinsz) + c->tcpwinsz = channel_tcpwinsz(); + if (c->dynamic_window > 0) + c->tcpwinsz = channel_tcpwinsz(); + + limit = MIN(limit, 2 * c->tcpwinsz); if (c->istate == CHAN_INPUT_OPEN && limit > 0 && @@ -1615,14 +1636,20 @@ !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && c->local_window < c->local_window_max/2 && c->local_consumed > 0) { + u_int addition = 0; + /* adjust max window size if we are in a dynamic environment */ + if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { + addition = c->tcpwinsz - c->local_window_max; + c->local_window_max += addition; + } packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); packet_put_int(c->remote_id); - packet_put_int(c->local_consumed); + packet_put_int(c->local_consumed + addition); packet_send(); debug2("channel %d: window %d sent adjust %d", c->self, c->local_window, c->local_consumed); - c->local_window += c->local_consumed; + c->local_window += c->local_consumed + addition; c->local_consumed = 0; } return 1; @@ -2281,7 +2308,8 @@ static int channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) + const char *host_to_connect, u_short port_to_connect, int gateway_ports, + int hpn_disabled, int hpn_buffer_size) { Channel *c; int sock, r, success = 0, wildcard = 0, is_client; @@ -2394,9 +2422,15 @@ continue; } /* Allocate a channel number for the socket. */ - c = channel_new("port listener", type, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, - 0, "port listener", 1); + /* explicitly test for hpn disabled option. if true use smaller window size */ + if (hpn_disabled) + c = channel_new("port listener", type, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); + else + c = channel_new("port listener", type, sock, sock, -1, + hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); strlcpy(c->path, host, sizeof(c->path)); c->host_port = port_to_connect; c->listening_port = listen_port; @@ -2433,20 +2467,22 @@ /* protocol local port fwd, used by ssh (and sshd in v1) */ int channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) + const char *host_to_connect, u_short port_to_connect, int gateway_ports, + int hpn_disabled, int hpn_buffer_size) { return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, listen_host, listen_port, host_to_connect, port_to_connect, - gateway_ports); + gateway_ports, hpn_disabled, hpn_buffer_size); } /* protocol v2 remote port fwd, used by sshd */ int channel_setup_remote_fwd_listener(const char *listen_address, - u_short listen_port, int gateway_ports) + u_short listen_port, int gateway_ports, int hpn_disabled, int hpn_buffer_size) { return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, - listen_address, listen_port, NULL, 0, gateway_ports); + listen_address, listen_port, NULL, 0, gateway_ports, + hpn_disabled, hpn_buffer_size); } /* @@ -2555,7 +2591,8 @@ */ void -channel_input_port_forward_request(int is_root, int gateway_ports) +channel_input_port_forward_request(int is_root, int gateway_ports, + int hpn_disabled, int hpn_buffer_size) { u_short port, host_port; char *hostname; @@ -2580,7 +2617,7 @@ /* Initiate forwarding */ channel_setup_local_fwd_listener(NULL, port, hostname, - host_port, gateway_ports); + host_port, gateway_ports, hpn_disabled, hpn_buffer_size); /* Free the argument string. */ xfree(hostname); @@ -2750,7 +2787,8 @@ */ int x11_create_display_inet(int x11_display_offset, int x11_use_localhost, - int single_connection, u_int *display_numberp, int **chanids) + int single_connection, u_int *display_numberp, int **chanids, + int hpn_disabled, int hpn_buffer_size) { Channel *nc = NULL; int display_number, sock; @@ -2847,10 +2885,16 @@ *chanids = xmalloc(sizeof(**chanids) * (num_socks + 1)); for (n = 0; n < num_socks; n++) { sock = socks[n]; - nc = channel_new("x11 listener", - SSH_CHANNEL_X11_LISTENER, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, - 0, "X11 inet listener", 1); + if (hpn_disabled) + nc = channel_new("x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, "X11 inet listener", 1); + else + nc = channel_new("x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, + hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, + 0, "X11 inet listener", 1); nc->single_connection = single_connection; (*chanids)[n] = nc->self; } diff -Naur --exclude=autom4te.cache openssh-4.3p2/channels.h openssh-4.3p2-gssapi/channels.h --- openssh-4.3p2/channels.h 2005-12-30 23:22:32.000000000 -0600 +++ openssh-4.3p2-gssapi/channels.h 2006-07-26 15:17:38.000000000 -0500 @@ -100,8 +100,10 @@ u_int local_window_max; u_int local_consumed; u_int local_maxpacket; + int dynamic_window; int extended_usage; int single_connection; + u_int tcpwinsz; char *ctype; /* type */ @@ -123,12 +125,17 @@ #define CHAN_EXTENDED_WRITE 2 /* default window/packet sizes for tcp/x11-fwd-channel */ -#define CHAN_SES_PACKET_DEFAULT (32*1024) -#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) -#define CHAN_TCP_PACKET_DEFAULT (32*1024) -#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) -#define CHAN_X11_PACKET_DEFAULT (16*1024) -#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) +#define CHAN_SES_PACKET_DEFAULT (32*1024) +#define CHAN_SES_WINDOW_DEFAULT_HPN (160*CHAN_TCP_PACKET_DEFAULT) +#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) + +#define CHAN_TCP_PACKET_DEFAULT (32*1024) +#define CHAN_TCP_WINDOW_DEFAULT_HPN (160*CHAN_TCP_PACKET_DEFAULT) +#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) + +#define CHAN_X11_PACKET_DEFAULT (16*1024) +#define CHAN_X11_WINDOW_DEFAULT_HPN (4*CHAN_X11_PACKET_DEFAULT) +#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) /* possible input states */ #define CHAN_INPUT_OPEN 0 @@ -208,21 +215,21 @@ void channel_permit_all_opens(void); void channel_add_permitted_opens(char *, int); void channel_clear_permitted_opens(void); -void channel_input_port_forward_request(int, int); +void channel_input_port_forward_request(int, int, int, int); int channel_connect_to(const char *, u_short); int channel_connect_by_listen_address(u_short); void channel_request_remote_forwarding(const char *, u_short, const char *, u_short); int channel_setup_local_fwd_listener(const char *, u_short, - const char *, u_short, int); + const char *, u_short, int, int, int); void channel_request_rforward_cancel(const char *host, u_short port); -int channel_setup_remote_fwd_listener(const char *, u_short, int); +int channel_setup_remote_fwd_listener(const char *, u_short, int, int, int); int channel_cancel_rport_listener(const char *, u_short); /* x11 forwarding */ int x11_connect_display(void); -int x11_create_display_inet(int, int, int, u_int *, int **); +int x11_create_display_inet(int, int, int, u_int *, int **, int, int); void x11_input_open(int, u_int32_t, void *); void x11_request_forwarding_with_spoofing(int, const char *, const char *, const char *); diff -Naur --exclude=autom4te.cache openssh-4.3p2/cipher.c openssh-4.3p2-gssapi/cipher.c --- openssh-4.3p2/cipher.c 2005-12-19 00:40:40.000000000 -0600 +++ openssh-4.3p2-gssapi/cipher.c 2006-07-26 15:17:38.000000000 -0500 @@ -151,7 +151,8 @@ for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); - if (c == NULL || c->number != SSH_CIPHER_SSH2) { + if (c == NULL || (c->number != SSH_CIPHER_SSH2 && + c->number != SSH_CIPHER_NONE)) { debug("bad cipher %s [%s]", p, names); xfree(cipher_list); return 0; @@ -325,6 +326,7 @@ int evplen; switch (c->number) { + case SSH_CIPHER_NONE: case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: @@ -359,6 +361,7 @@ int evplen = 0; switch (c->number) { + case SSH_CIPHER_NONE: case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: diff -Naur --exclude=autom4te.cache openssh-4.3p2/clientloop.c openssh-4.3p2-gssapi/clientloop.c --- openssh-4.3p2/clientloop.c 2005-12-30 23:22:32.000000000 -0600 +++ openssh-4.3p2-gssapi/clientloop.c 2006-07-26 15:17:38.000000000 -0500 @@ -689,6 +689,10 @@ u_int i, len, env_len, command, flags; uid_t euid; gid_t egid; + int listen_port = 0; + int connect_port = 0; + char * listen_host = NULL; + char * connect_host = NULL; /* * Accept connection on control socket @@ -737,6 +741,13 @@ command = buffer_get_int(&m); flags = buffer_get_int(&m); + if (SSHMUX_FLAG_PORTFORWARD & flags) + { + listen_host = buffer_get_string(&m,NULL); + listen_port = buffer_get_int(&m); + connect_host = buffer_get_string(&m,NULL); + connect_port = buffer_get_int(&m); + } buffer_clear(&m); switch (command) { @@ -776,6 +787,31 @@ return; } + if (allowed && (SSHMUX_FLAG_PORTFORWARD & flags) && listen_host && connect_host) + { + int ret; + Forward * fwd; + + fwd = &options.local_forwards[options.num_local_forwards++]; + fwd->listen_host = xstrdup(listen_host); + fwd->listen_port = listen_port; + fwd->connect_host = xstrdup(connect_host); + fwd->connect_port = connect_port; + ret = channel_setup_local_fwd_listener( + options.local_forwards[options.num_local_forwards-1].listen_host, + options.local_forwards[options.num_local_forwards-1].listen_port, + options.local_forwards[options.num_local_forwards-1].connect_host, + options.local_forwards[options.num_local_forwards-1].connect_port, + options.gateway_ports, options.hpn_disabled, options.hpn_buffer_size); + + } + + + if (listen_host) + xfree(listen_host); + if (connect_host) + xfree(connect_host); + /* Reply for SSHMUX_COMMAND_OPEN */ buffer_clear(&m); buffer_put_int(&m, allowed); @@ -874,11 +910,16 @@ set_nonblock(client_fd); - c = channel_new("session", SSH_CHANNEL_OPENING, - new_fd[0], new_fd[1], new_fd[2], - CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT, - CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); - + if (options.hpn_disabled) + c = channel_new("session", SSH_CHANNEL_OPENING, + new_fd[0], new_fd[1], new_fd[2], + CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT, + CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); + else + c = channel_new("session", SSH_CHANNEL_OPENING, + new_fd[0], new_fd[1], new_fd[2], + options.hpn_buffer_size, CHAN_SES_PACKET_DEFAULT, + CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); /* XXX */ c->ctl_fd = client_fd; @@ -973,7 +1014,8 @@ if (local) { if (channel_setup_local_fwd_listener(fwd.listen_host, fwd.listen_port, fwd.connect_host, - fwd.connect_port, options.gateway_ports) < 0) { + fwd.connect_port, options.gateway_ports, + options.hpn_disabled, options.hpn_buffer_size) < 0) { logit("Port forwarding failed."); goto out; } @@ -1669,10 +1711,16 @@ xfree(listen_address); return NULL; } - c = channel_new("forwarded-tcpip", - SSH_CHANNEL_CONNECTING, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - originator_address, 1); + if (options.hpn_disabled) + c = channel_new("forwarded-tcpip", + SSH_CHANNEL_CONNECTING, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + originator_address, 1); + else + c = channel_new("forwarded-tcpip", + SSH_CHANNEL_CONNECTING, sock, sock, -1, + options.hpn_buffer_size, options.hpn_buffer_size, 0, + originator_address, 1); xfree(originator_address); xfree(listen_address); return c; @@ -1706,9 +1754,14 @@ sock = x11_connect_display(); if (sock < 0) return NULL; - c = channel_new("x11", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + if (options.hpn_disabled) + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + else + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); c->force_drain = 1; return c; } @@ -1727,10 +1780,16 @@ sock = ssh_get_authentication_socket(); if (sock < 0) return NULL; - c = channel_new("authentication agent connection", - SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - "authentication agent connection", 1); + if (options.hpn_disabled) + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + "authentication agent connection", 1); + else + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, + options.hpn_buffer_size, options.hpn_buffer_size, 0, + "authentication agent connection", 1); c->force_drain = 1; return c; } diff -Naur --exclude=autom4te.cache openssh-4.3p2/clientloop.h openssh-4.3p2-gssapi/clientloop.h --- openssh-4.3p2/clientloop.h 2005-07-05 18:44:19.000000000 -0500 +++ openssh-4.3p2-gssapi/clientloop.h 2006-07-26 15:17:38.000000000 -0500 @@ -50,8 +50,10 @@ #define SSHMUX_COMMAND_OPEN 1 /* Open new connection */ #define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */ #define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */ +#define SSHMUX_COMMAND_PORTFORWARD 4 /* Ask master to portforward */ #define SSHMUX_FLAG_TTY (1) /* Request tty on open */ #define SSHMUX_FLAG_SUBSYS (1<<1) /* Subsystem request on open */ #define SSHMUX_FLAG_X11_FWD (1<<2) /* Request X11 forwarding */ #define SSHMUX_FLAG_AGENT_FWD (1<<3) /* Request agent forwarding */ +#define SSHMUX_FLAG_PORTFORWARD (1<<4) /* Request portforward */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/compat.c openssh-4.3p2-gssapi/compat.c --- openssh-4.3p2/compat.c 2005-03-01 04:24:33.000000000 -0600 +++ openssh-4.3p2-gssapi/compat.c 2006-07-26 15:17:38.000000000 -0500 @@ -162,6 +162,14 @@ strlen(check[i].pat), 0) == 1) { debug("match: %s pat %s", version, check[i].pat); datafellows = check[i].bugs; + /* Check to see if the remote side is OpenSSH and not HPN */ + if(strstr(version,"OpenSSH") != NULL) + { + if (strstr(version,"hpn") == NULL) + { + datafellows |= SSH_BUG_LARGEWINDOW; + } + } return; } } diff -Naur --exclude=autom4te.cache openssh-4.3p2/compat.h openssh-4.3p2-gssapi/compat.h --- openssh-4.3p2/compat.h 2005-03-01 04:24:33.000000000 -0600 +++ openssh-4.3p2-gssapi/compat.h 2006-07-26 15:17:38.000000000 -0500 @@ -56,6 +56,7 @@ #define SSH_BUG_PROBE 0x00400000 #define SSH_BUG_FIRSTKEX 0x00800000 #define SSH_OLD_FORWARD_ADDR 0x01000000 +#define SSH_BUG_LARGEWINDOW 0x02000000 void enable_compat13(void); void enable_compat20(void); diff -Naur --exclude=autom4te.cache openssh-4.3p2/config.h.in openssh-4.3p2-gssapi/config.h.in --- openssh-4.3p2/config.h.in 2006-02-10 18:07:35.000000000 -0600 +++ openssh-4.3p2-gssapi/config.h.in 2006-07-26 15:17:43.000000000 -0500 @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */ +#undef AFS_KRB5 + /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address */ #undef AIX_GETNAMEINFO_HACK @@ -7,6 +10,9 @@ /* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */ #undef AIX_LOGINFAILED_4ARG +/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */ +#undef AKLOG_PATH + /* Define if your resolver libs need this for getrrsetbyname */ #undef BIND_8_COMPAT @@ -125,6 +131,9 @@ /* Define if your system glob() function has gl_matchc options in glob_t */ #undef GLOB_HAS_GL_MATCHC +/* Define if you want GSI/Globus authentication support. */ +#undef GSI + /* Define this if you want GSSAPI support in the version 2 protocol */ #undef GSSAPI @@ -365,6 +374,10 @@ /* Define to 1 if you have the `glob' function. */ #undef HAVE_GLOB +/* Define to 1 if you have the `globus_gss_assist_map_and_authorize' function. + */ +#undef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + /* Define to 1 if you have the header file. */ #undef HAVE_GLOB_H @@ -1070,6 +1083,9 @@ /* Set this to your mail directory if you don't have maillock.h */ #undef MAIL_DIRECTORY +/* Define this if you're building with GSSAPI MechGlue. */ +#undef MECHGLUE + /* Define on *nto-qnx systems */ #undef MISSING_FD_MASK @@ -1128,6 +1144,9 @@ /* Location of PRNGD/EGD random number socket */ #undef PRNGD_SOCKET +/* Define this if you want support for startup/shutdown hooks */ +#undef SESSION_HOOKS + /* Define if your platform breaks doing a seteuid before a setuid */ #undef SETEUID_BREAKS_SETUID @@ -1213,6 +1232,9 @@ /* Use btmp to log bad logins */ #undef USE_BTMP +/* platform uses an in-memory credentials cache */ +#undef USE_CCAPI + /* Use libedit for sftp */ #undef USE_LIBEDIT @@ -1228,6 +1250,9 @@ /* Define if you want smartcard support using sectok */ #undef USE_SECTOK +/* platform has the Security Authorization Session API */ +#undef USE_SECURITY_SESSION_API + /* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ #undef WITH_ABBREV_NO_TTY diff -Naur --exclude=autom4te.cache openssh-4.3p2/configure openssh-4.3p2-gssapi/configure --- openssh-4.3p2/configure 2006-02-10 18:07:37.000000000 -0600 +++ openssh-4.3p2-gssapi/configure 2006-07-26 15:17:44.000000000 -0500 @@ -312,7 +312,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT build build_cpu build_vendor build_os host host_cpu host_vendor host_os AWK CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA EGREP AR CAT KILL PERL SED ENT TEST_MINUS_S_SH SH TEST_SHELL PATH_GROUPADD_PROG PATH_USERADD_PROG MAKE_PACKAGE_SUPPORTED STARTUP_SCRIPT_SHELL LOGIN_PROGRAM_FALLBACK PATH_PASSWD_PROG LD LIBWRAP LIBEDIT LIBPAM INSTALL_SSH_RAND_HELPER SSH_PRIVSEP_USER PROG_LS PROG_NETSTAT PROG_ARP PROG_IFCONFIG PROG_JSTAT PROG_PS PROG_SAR PROG_W PROG_WHO PROG_LAST PROG_LASTLOG PROG_DF PROG_VMSTAT PROG_UPTIME PROG_IPCS PROG_TAIL INSTALL_SSH_PRNG_CMDS OPENSC_CONFIG PRIVSEP_PATH xauth_path STRIP_OPT XAUTH_PATH NROFF MANTYPE mansubdir user_path piddir LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT build build_cpu build_vendor build_os host host_cpu host_vendor host_os AWK CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA EGREP AR CAT KILL PERL SED ENT TEST_MINUS_S_SH SH TEST_SHELL PATH_GROUPADD_PROG PATH_USERADD_PROG MAKE_PACKAGE_SUPPORTED STARTUP_SCRIPT_SHELL LOGIN_PROGRAM_FALLBACK PATH_PASSWD_PROG LD INSTALL_GSISSH LIBWRAP LIBEDIT LIBPAM INSTALL_SSH_RAND_HELPER SSH_PRIVSEP_USER PROG_LS PROG_NETSTAT PROG_ARP PROG_IFCONFIG PROG_JSTAT PROG_PS PROG_SAR PROG_W PROG_WHO PROG_LAST PROG_LASTLOG PROG_DF PROG_VMSTAT PROG_UPTIME PROG_IPCS PROG_TAIL INSTALL_SSH_PRNG_CMDS OPENSC_CONFIG PRIVSEP_PATH xauth_path STRIP_OPT XAUTH_PATH NROFF MANTYPE mansubdir user_path piddir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -873,6 +873,11 @@ --with-Werror Build main code with -Werror --with-zlib=PATH Use zlib in PATH --without-zlib-version-check Disable zlib version check + --with-mechglue=PATH Build with GSSAPI mechglue library + --with-gsi Enable Globus GSI authentication support + --with-globus Enable Globus GSI authentication support + --with-globus-static Link statically with Globus GSI libraries + --with-globus-flavor=TYPE Specify Globus flavor type (ex: gcc32dbg) --with-skey[=PATH] Enable S/Key support (optionally in PATH) --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH) --with-libedit[=PATH] Enable libedit support for sftp @@ -887,6 +892,8 @@ --with-sectok Enable smartcard support using libsectok --with-opensc[=PFX] Enable smartcard support using OpenSC (optionally in PATH) --with-kerberos5=PATH Enable Kerberos 5 support + --with-afs-krb5[=AKLOG_PATH] Enable aklog to get token (default=/usr/bin/aklog). + --with-session-hooks Enable hooks for executing external commands before/after a session --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty) --with-xauth=PATH Specify path to xauth program --with-mantype=man|cat|doc Set man page type @@ -5220,71 +5227,147 @@ ;; *-*-darwin*) - echo "$as_me:$LINENO: checking if we have working getaddrinfo" >&5 -echo $ECHO_N "checking if we have working getaddrinfo... $ECHO_C" >&6 - if test "$cross_compiling" = yes; then - echo "$as_me:$LINENO: result: assume it is working" >&5 -echo "${ECHO_T}assume it is working" >&6 -else - cat >conftest.$ac_ext <<_ACEOF + +cat >>confdefs.h <<\_ACEOF +#define BROKEN_GETADDRINFO 1 +_ACEOF +], + cat >>confdefs.h <<\_ACEOF +#define SETEUID_BREAKS_SETUID 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define BROKEN_SETREUID 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define BROKEN_SETREGID 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define BIND_8_COMPAT 1 +_ACEOF + + echo "$as_me:$LINENO: checking if we have the Security Authorization Session API" >&5 +echo $ECHO_N "checking if we have the Security Authorization Session API... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include -main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - exit(0); - else - exit(1); +#include +int +main () +{ +SessionCreate(0, 0); + ; + return 0; } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - echo "$as_me:$LINENO: result: working" >&5 -echo "${ECHO_T}working" >&6 -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -echo "$as_me:$LINENO: result: buggy" >&5 -echo "${ECHO_T}buggy" >&6 + ac_cv_use_security_session_api="yes" cat >>confdefs.h <<\_ACEOF -#define BROKEN_GETADDRINFO 1 +#define USE_SECURITY_SESSION_API 1 _ACEOF + LIBS="$LIBS -framework Security" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_use_security_session_api="no" + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - cat >>confdefs.h <<\_ACEOF -#define SETEUID_BREAKS_SETUID 1 +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + echo "$as_me:$LINENO: checking if we have an in-memory credentials cache" >&5 +echo $ECHO_N "checking if we have an in-memory credentials cache... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ _ACEOF - - cat >>confdefs.h <<\_ACEOF -#define BROKEN_SETREUID 1 +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +cc_context_t c; + (void) cc_initialize (&c, 0, NULL, NULL); + ; + return 0; +} _ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then - cat >>confdefs.h <<\_ACEOF -#define BROKEN_SETREGID 1 +cat >>confdefs.h <<\_ACEOF +#define USE_CCAPI 1 _ACEOF + LIBS="$LIBS -framework Security" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + if test "x$ac_cv_use_security_session_api" = "xno"; then + { { echo "$as_me:$LINENO: error: *** Need a security framework to use the credentials cache API ***" >&5 +echo "$as_me: error: *** Need a security framework to use the credentials cache API ***" >&2;} + { (exit 1); exit 1; }; } + fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -cat >>confdefs.h <<_ACEOF -#define BIND_8_COMPAT 1 -_ACEOF +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ;; *-*-hpux*) # first we define all of the options common to all HP-UX releases @@ -10381,38 +10464,456 @@ int main(void){struct dirent d;exit(sizeof(d.d_name)<=sizeof(char));} _ACEOF -rm -f conftest$ac_exeext +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +cat >>confdefs.h <<\_ACEOF +#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1 +_ACEOF + + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# Check whether the user wants GSSAPI mechglue support + +# Check whether --with-mechglue or --without-mechglue was given. +if test "${with_mechglue+set}" = set; then + withval="$with_mechglue" + + echo "$as_me:$LINENO: checking for mechglue library" >&5 +echo $ECHO_N "checking for mechglue library... $ECHO_C" >&6 + + if test -e ${withval}/libgssapi.a ; then + mechglue_lib=${withval}/libgssapi.a + elif test -e ${withval}/lib/libgssapi.a ; then + mechglue_lib=${withval}/lib/libgssapi.a + else + { { echo "$as_me:$LINENO: error: \"Can't find libgssapi in ${withval}\"" >&5 +echo "$as_me: error: \"Can't find libgssapi in ${withval}\"" >&2;} + { (exit 1); exit 1; }; }; + fi + LIBS="$LIBS ${mechglue_lib}" + echo "$as_me:$LINENO: result: ${mechglue_lib}" >&5 +echo "${ECHO_T}${mechglue_lib}" >&6 + + +echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + + if test $ac_cv_lib_dl_dlopen = yes; then + LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic" + fi + + cat >>confdefs.h <<\_ACEOF +#define GSSAPI 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define MECHGLUE 1 +_ACEOF + + GSSAPI="mechglue" + + + +fi; + + +# Check whether the user wants GSI (Globus) support +gsi_path="no" + +# Check whether --with-gsi or --without-gsi was given. +if test "${with_gsi+set}" = set; then + withval="$with_gsi" + + gsi_path="$withval" + + +fi; + + +# Check whether --with-globus or --without-globus was given. +if test "${with_globus+set}" = set; then + withval="$with_globus" + + gsi_path="$withval" + + +fi; + + +# Check whether --with-globus-static or --without-globus-static was given. +if test "${with_globus_static+set}" = set; then + withval="$with_globus_static" + + gsi_static="-static" + if test "x$gsi_path" = "xno" ; then + gsi_path="$withval" + fi + + +fi; + +# Check whether the user has a Globus flavor type +globus_flavor_type="no" + +# Check whether --with-globus-flavor or --without-globus-flavor was given. +if test "${with_globus_flavor+set}" = set; then + withval="$with_globus_flavor" + + globus_flavor_type="$withval" + if test "x$gsi_path" = "xno" ; then + gsi_path="yes" + fi + + +fi; + +if test "x$gsi_path" != "xno" ; then + # Globus GSSAPI configuration + echo "$as_me:$LINENO: checking for Globus GSI" >&5 +echo $ECHO_N "checking for Globus GSI... $ECHO_C" >&6 + +cat >>confdefs.h <<\_ACEOF +#define GSI 1 +_ACEOF + + + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + { { echo "$as_me:$LINENO: error: Previously configured GSSAPI library conflicts with Globus GSI." >&5 +echo "$as_me: error: Previously configured GSSAPI library conflicts with Globus GSI." >&2;} + { (exit 1); exit 1; }; } + fi + if test -z "$GSSAPI"; then + cat >>confdefs.h <<\_ACEOF +#define GSSAPI 1 +_ACEOF + + GSSAPI="GSI" + fi + + if test "x$gsi_path" = "xyes" ; then + if test -z "$GLOBUS_LOCATION" ; then + { { echo "$as_me:$LINENO: error: GLOBUS_LOCATION environment variable must be set." >&5 +echo "$as_me: error: GLOBUS_LOCATION environment variable must be set." >&2;} + { (exit 1); exit 1; }; } + else + gsi_path="$GLOBUS_LOCATION" + fi + fi + GLOBUS_LOCATION="$gsi_path" + export GLOBUS_LOCATION + if test ! -d "$GLOBUS_LOCATION" ; then + { { echo "$as_me:$LINENO: error: Cannot find Globus installation. Set GLOBUS_LOCATION environment variable." >&5 +echo "$as_me: error: Cannot find Globus installation. Set GLOBUS_LOCATION environment variable." >&2;} + { (exit 1); exit 1; }; } + fi + + if test "x$globus_flavor_type" = "xno" ; then + { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must be specified" >&5 +echo "$as_me: error: --with-globus-flavor=TYPE must be specified" >&2;} + { (exit 1); exit 1; }; } + fi + if test "x$globus_flavor_type" = "xyes" ; then + { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must specify a flavor type" >&5 +echo "$as_me: error: --with-globus-flavor=TYPE must specify a flavor type" >&2;} + { (exit 1); exit 1; }; } + fi + + GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}" + if test ! -d "$GLOBUS_INCLUDE" ; then + { { echo "$as_me:$LINENO: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&5 +echo "$as_me: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&2;} + { (exit 1); exit 1; }; } + fi + GSI_CPPFLAGS="-I${GLOBUS_INCLUDE}" + + if test -x ${gsi_path}/bin/globus-makefile-header ; then + GSI_LIBS=`${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'` + elif test -x ${gsi_path}/sbin/globus-makefile-header ; then + GSI_LIBS=`${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'` + else + { { echo "$as_me:$LINENO: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&5 +echo "$as_me: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&2;} + { (exit 1); exit 1; }; } + fi + if test -n "${need_dash_r}"; then + GSI_LDFLAGS="-L${gsi_path}/lib -R{gsi_path}/lib" + else + GSI_LDFLAGS="-L${gsi_path}/lib" + fi + if test -z "$GSI_LIBS" ; then + { { echo "$as_me:$LINENO: error: globus-makefile-header failed" >&5 +echo "$as_me: error: globus-makefile-header failed" >&2;} + { (exit 1); exit 1; }; } + fi + + cat >>confdefs.h <<\_ACEOF +#define HAVE_GSSAPI_H 1 +_ACEOF + + + LIBS="$LIBS $GSI_LIBS" + LDFLAGS="$LDFLAGS $GSI_LDFLAGS" + CPPFLAGS="$CPPFLAGS $GSI_CPPFLAGS" + + # test that we got the libraries OK + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { { echo "$as_me:$LINENO: error: link with Globus libraries failed" >&5 +echo "$as_me: error: link with Globus libraries failed" >&2;} + { (exit 1); exit 1; }; } + + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +for ac_func in globus_gss_assist_map_and_authorize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + eval "$as_ac_var=yes" else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 + echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -( exit $ac_status ) - - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - -cat >>confdefs.h <<\_ACEOF -#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1 +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF - fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +done + + INSTALL_GSISSH="yes" +else + INSTALL_GSISSH="" fi +# End Globus/GSI section + echo "$as_me:$LINENO: checking for /proc/pid/fd directory" >&5 echo $ECHO_N "checking for /proc/pid/fd directory... $ECHO_C" >&6 if test -d "/proc/$$/fd" ; then @@ -14823,7 +15324,9 @@ fi; +if test -z "$GSI_LIBS" ; then LIBS="-lcrypto $LIBS" +fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -24956,7 +25459,165 @@ - fi + # If we're using some other GSSAPI + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + { { echo "$as_me:$LINENO: error: $GSSAPI GSSAPI library conflicts with Kerberos support. Use mechglue instead." >&5 +echo "$as_me: error: $GSSAPI GSSAPI library conflicts with Kerberos support. Use mechglue instead." >&2;} + { (exit 1); exit 1; }; } + fi + + if test -z "$GSSAPI"; then + GSSAPI="KRB5"; + fi + + oldCPP="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" + if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then + echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5 +echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6 +if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5 +echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking gssapi_krb5.h usability" >&5 +echo $ECHO_N "checking gssapi_krb5.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking gssapi_krb5.h presence" >&5 +echo $ECHO_N "checking gssapi_krb5.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------- ## +## Report this to openssh-unix-dev@mindrot.org ## +## ------------------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5 +echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6 +if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_gssapi_krb5_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5 +echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6 + +fi +if test $ac_cv_header_gssapi_krb5_h = yes; then + : +else + CPPFLAGS="$oldCPP" +fi + + + + fi if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" fi @@ -25554,6 +26215,61 @@ fi; +# Check whether user wants AFS_KRB5 support +AFS_KRB5_MSG="no" + +# Check whether --with-afs-krb5 or --without-afs-krb5 was given. +if test "${with_afs_krb5+set}" = set; then + withval="$with_afs_krb5" + + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + +cat >>confdefs.h <<_ACEOF +#define AKLOG_PATH "$withval" +_ACEOF + + else + +cat >>confdefs.h <<_ACEOF +#define AKLOG_PATH "/usr/bin/aklog" +_ACEOF + + fi + + if test -z "$KRB5ROOT" ; then + { echo "$as_me:$LINENO: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&5 +echo "$as_me: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&2;} + fi + + LIBS="-lkrbafs -lkrb4 $LIBS" + if test ! -z "$AFS_LIBS" ; then + LIBS="$LIBS $AFS_LIBS" + fi + +cat >>confdefs.h <<\_ACEOF +#define AFS_KRB5 1 +_ACEOF + + AFS_KRB5_MSG="yes" + fi + + +fi; + + +# Check whether --with-session-hooks or --without-session-hooks was given. +if test "${with_session_hooks+set}" = set; then + withval="$with_session_hooks" + +cat >>confdefs.h <<\_ACEOF +#define SESSION_HOOKS 1 +_ACEOF + + +fi; + # Looking for programs, paths and files PRIVSEP_PATH=/var/empty @@ -27224,9 +27940,9 @@ exec 5>>config.log { echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <&5 cat >&5 <<_CSEOF @@ -27524,6 +28240,7 @@ s,@LOGIN_PROGRAM_FALLBACK@,$LOGIN_PROGRAM_FALLBACK,;t t s,@PATH_PASSWD_PROG@,$PATH_PASSWD_PROG,;t t s,@LD@,$LD,;t t +s,@INSTALL_GSISSH@,$INSTALL_GSISSH,;t t s,@LIBWRAP@,$LIBWRAP,;t t s,@LIBEDIT@,$LIBEDIT,;t t s,@LIBPAM@,$LIBPAM,;t t diff -Naur --exclude=autom4te.cache openssh-4.3p2/configure.ac openssh-4.3p2-gssapi/configure.ac --- openssh-4.3p2/configure.ac 2006-02-08 05:11:06.000000000 -0600 +++ openssh-4.3p2-gssapi/configure.ac 2006-07-26 15:17:38.000000000 -0500 @@ -216,21 +216,36 @@ AC_DEFINE(BROKEN_SETREGID) ;; *-*-darwin*) - AC_MSG_CHECKING(if we have working getaddrinfo) - AC_TRY_RUN([#include -main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - exit(0); - else - exit(1); -}], [AC_MSG_RESULT(working)], - [AC_MSG_RESULT(buggy) AC_DEFINE(BROKEN_GETADDRINFO, 1, [getaddrinfo is broken (if present)])], - [AC_MSG_RESULT(assume it is working)]) AC_DEFINE(SETEUID_BREAKS_SETUID) AC_DEFINE(BROKEN_SETREUID) AC_DEFINE(BROKEN_SETREGID) AC_DEFINE_UNQUOTED(BIND_8_COMPAT, 1, [Define if your resolver libs need this for getrrsetbyname]) + AC_MSG_CHECKING(if we have the Security Authorization Session API) + AC_TRY_COMPILE([#include ], + [SessionCreate(0, 0);], + [ac_cv_use_security_session_api="yes" + AC_DEFINE(USE_SECURITY_SESSION_API, 1, + [platform has the Security Authorization Session API]) + LIBS="$LIBS -framework Security" + AC_MSG_RESULT(yes)], + [ac_cv_use_security_session_api="no" + AC_MSG_RESULT(no)]) + AC_MSG_CHECKING(if we have an in-memory credentials cache) + AC_TRY_COMPILE( + [#include ], + [cc_context_t c; + (void) cc_initialize (&c, 0, NULL, NULL);], + [AC_DEFINE(USE_CCAPI, 1, + [platform uses an in-memory credentials cache]) + LIBS="$LIBS -framework Security" + AC_MSG_RESULT(yes) + if test "x$ac_cv_use_security_session_api" = "xno"; then + AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) + fi], + [AC_MSG_RESULT(no)] + ) ;; *-*-hpux*) # first we define all of the options common to all HP-UX releases @@ -957,6 +972,153 @@ ] ) +# Check whether the user wants GSSAPI mechglue support +AC_ARG_WITH(mechglue, + [ --with-mechglue=PATH Build with GSSAPI mechglue library], + [ + AC_MSG_CHECKING(for mechglue library) + + if test -e ${withval}/libgssapi.a ; then + mechglue_lib=${withval}/libgssapi.a + elif test -e ${withval}/lib/libgssapi.a ; then + mechglue_lib=${withval}/lib/libgssapi.a + else + AC_MSG_ERROR("Can't find libgssapi in ${withval}"); + fi + LIBS="$LIBS ${mechglue_lib}" + AC_MSG_RESULT(${mechglue_lib}) + + AC_CHECK_LIB(dl, dlopen, , ) + if test $ac_cv_lib_dl_dlopen = yes; then + LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic" + fi + + AC_DEFINE(GSSAPI) + AC_DEFINE(MECHGLUE, 1, [Define this if you're building with GSSAPI MechGlue.]) + GSSAPI="mechglue" + + ] +) + + +# Check whether the user wants GSI (Globus) support +gsi_path="no" +AC_ARG_WITH(gsi, + [ --with-gsi Enable Globus GSI authentication support], + [ + gsi_path="$withval" + ] +) + +AC_ARG_WITH(globus, + [ --with-globus Enable Globus GSI authentication support], + [ + gsi_path="$withval" + ] +) + +AC_ARG_WITH(globus-static, + [ --with-globus-static Link statically with Globus GSI libraries], + [ + gsi_static="-static" + if test "x$gsi_path" = "xno" ; then + gsi_path="$withval" + fi + ] +) + +# Check whether the user has a Globus flavor type +globus_flavor_type="no" +AC_ARG_WITH(globus-flavor, + [ --with-globus-flavor=TYPE Specify Globus flavor type (ex: gcc32dbg)], + [ + globus_flavor_type="$withval" + if test "x$gsi_path" = "xno" ; then + gsi_path="yes" + fi + ] +) + +if test "x$gsi_path" != "xno" ; then + # Globus GSSAPI configuration + AC_MSG_CHECKING(for Globus GSI) + AC_DEFINE(GSI, 1, [Define if you want GSI/Globus authentication support.]) + + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Globus GSI.]) + fi + if test -z "$GSSAPI"; then + AC_DEFINE(GSSAPI) + GSSAPI="GSI" + fi + + if test "x$gsi_path" = "xyes" ; then + if test -z "$GLOBUS_LOCATION" ; then + AC_MSG_ERROR(GLOBUS_LOCATION environment variable must be set.) + else + gsi_path="$GLOBUS_LOCATION" + fi + fi + GLOBUS_LOCATION="$gsi_path" + export GLOBUS_LOCATION + if test ! -d "$GLOBUS_LOCATION" ; then + AC_MSG_ERROR(Cannot find Globus installation. Set GLOBUS_LOCATION environment variable.) + fi + + if test "x$globus_flavor_type" = "xno" ; then + AC_MSG_ERROR(--with-globus-flavor=TYPE must be specified) + fi + if test "x$globus_flavor_type" = "xyes" ; then + AC_MSG_ERROR(--with-globus-flavor=TYPE must specify a flavor type) + fi + + GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}" + if test ! -d "$GLOBUS_INCLUDE" ; then + AC_MSG_ERROR(Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}) + fi + GSI_CPPFLAGS="-I${GLOBUS_INCLUDE}" + + if test -x ${gsi_path}/bin/globus-makefile-header ; then + GSI_LIBS=`${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'` + elif test -x ${gsi_path}/sbin/globus-makefile-header ; then + GSI_LIBS=`${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'` + else + AC_MSG_ERROR(Cannot find globus-makefile-header: Globus installation is incomplete) + fi + if test -n "${need_dash_r}"; then + GSI_LDFLAGS="-L${gsi_path}/lib -R{gsi_path}/lib" + else + GSI_LDFLAGS="-L${gsi_path}/lib" + fi + if test -z "$GSI_LIBS" ; then + AC_MSG_ERROR(globus-makefile-header failed) + fi + + AC_DEFINE(HAVE_GSSAPI_H) + + LIBS="$LIBS $GSI_LIBS" + LDFLAGS="$LDFLAGS $GSI_LDFLAGS" + CPPFLAGS="$CPPFLAGS $GSI_CPPFLAGS" + + # test that we got the libraries OK + AC_TRY_LINK( + [], + [], + [ + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_ERROR(link with Globus libraries failed) + ] + ) + AC_CHECK_FUNCS(globus_gss_assist_map_and_authorize) + INSTALL_GSISSH="yes" +else + INSTALL_GSISSH="" +fi +AC_SUBST(INSTALL_GSISSH) +# End Globus/GSI section + AC_MSG_CHECKING([for /proc/pid/fd directory]) if test -d "/proc/$$/fd" ; then AC_DEFINE(HAVE_PROC_PID, 1, [Define if you have /proc/$pid/fd]) @@ -1720,7 +1882,9 @@ fi ] ) +if test -z "$GSI_LIBS" ; then LIBS="-lcrypto $LIBS" +fi AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL, 1, [Define if your ssl headers are included with #include ]), @@ -3039,7 +3203,21 @@ AC_CHECK_HEADER(gssapi_krb5.h, , [ CPPFLAGS="$oldCPP" ]) - fi + # If we're using some other GSSAPI + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + AC_MSG_ERROR([$GSSAPI GSSAPI library conflicts with Kerberos support. Use mechglue instead.]) + fi + + if test -z "$GSSAPI"; then + GSSAPI="KRB5"; + fi + + oldCPP="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" + AC_CHECK_HEADER(gssapi_krb5.h, , + [ CPPFLAGS="$oldCPP" ]) + + fi if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" fi @@ -3058,6 +3236,42 @@ ] ) +# Check whether user wants AFS_KRB5 support +AFS_KRB5_MSG="no" +AC_ARG_WITH(afs-krb5, + [ --with-afs-krb5[[=AKLOG_PATH]] Enable aklog to get token (default=/usr/bin/aklog).], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + AC_DEFINE_UNQUOTED(AKLOG_PATH, "$withval", + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + else + AC_DEFINE_UNQUOTED(AKLOG_PATH, + "/usr/bin/aklog", + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + fi + + if test -z "$KRB5ROOT" ; then + AC_MSG_WARN([AFS_KRB5 requires Kerberos 5 support, build may fail]) + fi + + LIBS="-lkrbafs -lkrb4 $LIBS" + if test ! -z "$AFS_LIBS" ; then + LIBS="$LIBS $AFS_LIBS" + fi + AC_DEFINE(AFS_KRB5, 1, + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + AFS_KRB5_MSG="yes" + fi + ] +) + +AC_ARG_WITH(session-hooks, + [ --with-session-hooks Enable hooks for executing external commands before/after a session], + [ AC_DEFINE(SESSION_HOOKS, 1, [Define this if you want support for startup/shutdown hooks]) ] +) + # Looking for programs, paths and files PRIVSEP_PATH=/var/empty diff -Naur --exclude=autom4te.cache openssh-4.3p2/gss-genr.c openssh-4.3p2-gssapi/gss-genr.c --- openssh-4.3p2/gss-genr.c 2005-11-04 22:07:05.000000000 -0600 +++ openssh-4.3p2-gssapi/gss-genr.c 2006-07-26 15:17:38.000000000 -0500 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-genr.c,v 1.6 2005/10/13 22:24:31 stevesk Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,13 +31,155 @@ #include "xmalloc.h" #include "bufaux.h" #include "log.h" +#include "canohost.h" #include "ssh2.h" +#include #include "ssh-gss.h" extern u_char *session_id2; extern u_int session_id2_len; +typedef struct { + char *encoded; + gss_OID oid; +} ssh_gss_kex_mapping; + +/* + * XXX - It would be nice to find a more elegant way of handling the + * XXX passing of the key exchange context to the userauth routines + */ + +Gssctxt *gss_kex_context = NULL; + +static ssh_gss_kex_mapping *gss_enc2oid = NULL; + +int +ssh_gssapi_oid_table_ok() { + return (gss_enc2oid != NULL); +} + +/* + * Return a list of the gss-group1-sha1 mechanisms supported by this program + * + * We test mechanisms to ensure that we can use them, to avoid starting + * a key exchange with a bad mechanism + */ + + +char * +ssh_gssapi_client_mechanisms(const char *host) { + gss_OID_set gss_supported; + OM_uint32 min_status; + + gss_indicate_mechs(&min_status, &gss_supported); + + return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, + (void *)host)); +} + +char * +ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, + void *data) { + Buffer buf; + size_t i; + int oidpos, enclen; + char *mechs, *encoded; + u_char digest[EVP_MAX_MD_SIZE]; + char deroid[2]; + const EVP_MD *evp_md = EVP_md5(); + EVP_MD_CTX md; + + if (gss_enc2oid != NULL) { + for (i=0;gss_enc2oid[i].encoded!=NULL;i++) + xfree(gss_enc2oid[i].encoded); + xfree(gss_enc2oid); + } + + gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping)* + (gss_supported->count+1)); + + buffer_init(&buf); + + oidpos = 0; + for (i = 0;i < gss_supported->count;i++) { + if (gss_supported->elements[i].length < 128 && + (*check)(&(gss_supported->elements[i]), data)) { + + deroid[0] = SSH_GSS_OIDTYPE; + deroid[1] = gss_supported->elements[i].length; + + EVP_DigestInit(&md, evp_md); + EVP_DigestUpdate(&md, deroid, 2); + EVP_DigestUpdate(&md, + gss_supported->elements[i].elements, + gss_supported->elements[i].length); + EVP_DigestFinal(&md, digest, NULL); + + encoded = xmalloc(EVP_MD_size(evp_md)*2); + enclen = __b64_ntop(digest, EVP_MD_size(evp_md), + encoded, EVP_MD_size(evp_md)*2); + + if (oidpos != 0) + buffer_put_char(&buf, ','); + + buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, + sizeof(KEX_GSS_GEX_SHA1_ID)-1); + buffer_append(&buf, encoded, enclen); + buffer_put_char(&buf,','); + buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, + sizeof(KEX_GSS_GRP1_SHA1_ID)-1); + buffer_append(&buf, encoded, enclen); + + gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); + gss_enc2oid[oidpos].encoded = encoded; + oidpos++; + } + } + gss_enc2oid[oidpos].oid = NULL; + gss_enc2oid[oidpos].encoded = NULL; + + buffer_put_char(&buf, '\0'); + + mechs = xmalloc(buffer_len(&buf)); + buffer_get(&buf, mechs, buffer_len(&buf)); + buffer_free(&buf); + + if (strlen(mechs) == 0) { + xfree(mechs); + mechs = NULL; + } + + return (mechs); +} + +gss_OID +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int *gex) { + int i = 0; + + if (strncmp(name, KEX_GSS_GRP1_SHA1_ID, + sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) { + name+=sizeof(KEX_GSS_GRP1_SHA1_ID)-1; + *gex = 0; + } else if (strncmp(name, KEX_GSS_GEX_SHA1_ID, + sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) { + name+=sizeof(KEX_GSS_GEX_SHA1_ID)-1; + *gex = 1; + } else { + return NULL; + } + + while (gss_enc2oid[i].encoded != NULL && + strcmp(name, gss_enc2oid[i].encoded) != 0) { + i++; + } + + if (gss_enc2oid[i].oid != NULL && ctx != NULL) + ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); + + return gss_enc2oid[i].oid; +} + /* Check that the OID in a data stream matches that in the context */ int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) @@ -96,7 +238,7 @@ /* The GSSAPI error */ do { gss_display_status(&lmin, ctxt->major, - GSS_C_GSS_CODE, GSS_C_NULL_OID, &ctx, &msg); + GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg); buffer_append(&b, msg.value, msg.length); buffer_put_char(&b, '\n'); @@ -107,7 +249,7 @@ /* The mechanism specific error */ do { gss_display_status(&lmin, ctxt->minor, - GSS_C_MECH_CODE, GSS_C_NULL_OID, &ctx, &msg); + GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg); buffer_append(&b, msg.value, msg.length); buffer_put_char(&b, '\n'); @@ -146,10 +288,13 @@ void ssh_gssapi_delete_ctx(Gssctxt **ctx) { +#if !defined(MECHGLUE) OM_uint32 ms; +#endif if ((*ctx) == NULL) return; +#if !defined(MECHGLUE) /* mechglue has some memory management issues */ if ((*ctx)->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER); if ((*ctx)->name != GSS_C_NO_NAME) @@ -165,6 +310,7 @@ gss_release_name(&ms, &(*ctx)->client); if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &(*ctx)->client_creds); +#endif xfree(*ctx); *ctx = NULL; @@ -203,15 +349,25 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) { gss_buffer_desc gssbuf; + char *xhost; - gssbuf.length = sizeof("host@") + strlen(host); + /* Make a copy of the host name, in case it was returned by a + * previous call to gethostbyname(). */ + xhost = xstrdup(host); + + /* Make sure we have the FQDN. Some GSSAPI implementations don't do + * this for us themselves */ + resolve_localhost(&xhost); + + gssbuf.length = sizeof("host@") + strlen(xhost); gssbuf.value = xmalloc(gssbuf.length); - snprintf(gssbuf.value, gssbuf.length, "host@%s", host); + snprintf(gssbuf.value, gssbuf.length, "host@%s", xhost); if ((ctx->major = gss_import_name(&ctx->minor, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) ssh_gssapi_error(ctx); + xfree(xhost); xfree(gssbuf.value); return (ctx->major); } @@ -248,6 +404,9 @@ OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) + return -1; + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); @@ -255,6 +414,19 @@ return (ctx->major); } +/* Priviledged when used by server */ +OM_uint32 +ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +{ + if (ctx == NULL) + return -1; + + ctx->major = gss_verify_mic(&ctx->minor, ctx->context, + gssbuf, gssmic, NULL); + + return (ctx->major); +} + void ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, const char *context) @@ -277,4 +449,19 @@ return (ssh_gssapi_acquire_cred(*ctx)); } +int +ssh_gssapi_check_mechanism(gss_OID oid, void *host) { + Gssctxt * ctx = NULL; + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + + ssh_gssapi_build_ctx(&ctx); + ssh_gssapi_set_oid(ctx, oid); + ssh_gssapi_import_name(ctx, host); + major = ssh_gssapi_init_ctx(ctx, 0, GSS_C_NO_BUFFER, &token, NULL); + gss_release_buffer(&minor, &token); + ssh_gssapi_delete_ctx(&ctx); + return (!GSS_ERROR(major)); +} + #endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/gss-serv.c openssh-4.3p2-gssapi/gss-serv.c --- openssh-4.3p2/gss-serv.c 2005-11-04 22:07:05.000000000 -0600 +++ openssh-4.3p2-gssapi/gss-serv.c 2006-07-26 15:17:38.000000000 -0500 @@ -36,9 +36,12 @@ #include "servconf.h" #include "xmalloc.h" #include "getput.h" +#include "monitor_wrap.h" #include "ssh-gss.h" +extern ServerOptions options; + static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}}; @@ -49,14 +52,46 @@ #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; #endif +#ifdef GSI +extern ssh_gssapi_mech gssapi_gsi_mech; +#endif ssh_gssapi_mech* supported_mechs[]= { #ifdef KRB5 &gssapi_kerberos_mech, #endif +#ifdef GSI + &gssapi_gsi_mech, +#endif &gssapi_null_mech, }; +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG +static int limited = 0; +#endif + +/* Unprivileged */ +char * +ssh_gssapi_server_mechanisms() { + gss_OID_set supported; + + ssh_gssapi_supported_oids(&supported); + return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, + NULL)); +} + +/* Unprivileged */ +int +ssh_gssapi_server_check_mech(gss_OID oid, void *data) { + Gssctxt * ctx = NULL; + int res; + + res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); + ssh_gssapi_delete_ctx(&ctx); + + return (res); +} + /* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) @@ -67,7 +102,8 @@ gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); - gss_indicate_mechs(&min_status, &supported); + /* Ask priviledged process what mechanisms it supports. */ + PRIVSEP(gss_indicate_mechs(&min_status, &supported)); while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, @@ -117,6 +153,10 @@ (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) { if (ssh_gssapi_getclient(ctx, &gssapi_client)) fatal("Couldn't convert client name"); +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG + if (flags && (*flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG)) + limited=1; +#endif } return (status); @@ -136,6 +176,17 @@ tok = ename->value; +#ifdef GSI /* GSI gss_export_name() is broken. */ + if ((ctx->oid->length == gssapi_gsi_mech.oid.length) && + (memcmp(ctx->oid->elements, gssapi_gsi_mech.oid.elements, + gssapi_gsi_mech.oid.length) == 0)) { + name->length = ename->length; + name->value = xmalloc(ename->length+1); + memcpy(name->value, ename->value, ename->length); + return GSS_S_COMPLETE; + } +#endif + /* * Check that ename is long enough for all of the fixed length * header, and that the initial ID bytes are correct @@ -225,6 +276,10 @@ /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; + + /* needed for globus_gss_assist_map_and_authorize() */ + client->context = ctx->context; + return (ctx->major); } @@ -277,6 +332,12 @@ debug("No suitable client data"); return 0; } +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG + if (limited && options.gsi_allow_limited_proxy != 1) { + debug("limited proxy not acceptable for remote login"); + return 0; + } +#endif if (gssapi_client.mech && gssapi_client.mech->userok) if ((*gssapi_client.mech->userok)(&gssapi_client, user)) return 1; @@ -293,14 +354,22 @@ return (0); } -/* Privileged */ -OM_uint32 -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +/* Priviledged */ +int +ssh_gssapi_localname(char **user) { - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, - gssbuf, gssmic, NULL); - - return (ctx->major); + *user = NULL; + if (gssapi_client.displayname.length==0 || + gssapi_client.displayname.value==NULL) { + debug("No suitable client data"); + return(0);; + } + if (gssapi_client.mech && gssapi_client.mech->localname) { + return((*gssapi_client.mech->localname)(&gssapi_client,user)); + } else { + debug("Unknown client authentication type"); + } + return(0); } #endif diff -Naur --exclude=autom4te.cache openssh-4.3p2/gss-serv-gsi.c openssh-4.3p2-gssapi/gss-serv-gsi.c --- openssh-4.3p2/gss-serv-gsi.c 1969-12-31 18:00:00.000000000 -0600 +++ openssh-4.3p2-gssapi/gss-serv-gsi.c 2006-07-26 15:17:38.000000000 -0500 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef GSSAPI +#ifdef GSI + +#include "auth.h" +#include "auth-pam.h" +#include "xmalloc.h" +#include "log.h" +#include "servconf.h" + +#include "ssh-gss.h" + +extern ServerOptions options; + +#include + +static int ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_gsi_mech = { + "dZuIebMjgUqaxvbF7hDbAw==", + "GSI", + {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"}, + NULL, + &ssh_gssapi_gsi_userok, + &ssh_gssapi_gsi_localname, + &ssh_gssapi_gsi_storecreds +}; + +/* + * Check if this user is OK to login under GSI. User has been authenticated + * as identity in global 'client_name.value' and is trying to log in as passed + * username in 'name'. + * + * Returns non-zero if user is authorized, 0 otherwise. + */ +static int +ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name) +{ + int authorized = 0; + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + name, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else if (strcmp(name, lname) != 0) { + debug("GSI user maps to %s, not %s", lname, name); + } else { + authorized = 1; + } +#else + debug("calling globus_gss_assist_userok()"); + if (GLOBUS_SUCCESS != + (res = (globus_gss_assist_userok(client->displayname.value, + name)))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else { + authorized = 1; + } +#endif + + logit("GSI user %s is%s authorized as target user %s", + (char *) client->displayname.value, (authorized ? "" : " not"), name); + + return authorized; +} + +/* + * Return the local username associated with the GSI credentials. + */ +int +ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user) +{ + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + NULL, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } + *user = strdup(lname); +#else + debug("calling globus_gss_assist_gridmap()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_gridmap(client->displayname.value, user))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } +#endif + + logit("GSI user %s mapped to target user %s", + (char *) client->displayname.value, *user); + + return 1; +} + +/* + * Export GSI credentials to disk. + */ +static void +ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client) +{ + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc export_cred = GSS_C_EMPTY_BUFFER; + char * p; + + if (!client || !client->creds) { + return; + } + + major_status = gss_export_cred(&minor_status, + client->creds, + GSS_C_NO_OID, + 1, + &export_cred); + if (GSS_ERROR(major_status) && major_status != GSS_S_UNAVAILABLE) { + Gssctxt *ctx; + ssh_gssapi_build_ctx(&ctx); + ctx->major = major_status; + ctx->minor = minor_status; + ssh_gssapi_set_oid(ctx, &gssapi_gsi_mech.oid); + ssh_gssapi_error(ctx); + ssh_gssapi_delete_ctx(&ctx); + return; + } + + p = strchr((char *) export_cred.value, '='); + if (p == NULL) { + logit("Failed to parse exported credentials string '%.100s'", + (char *)export_cred.value); + gss_release_buffer(&minor_status, &export_cred); + return; + } + *p++ = '\0'; + if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) { + client->store.envvar = strdup("X509_USER_PROXY"); + } else { + client->store.envvar = strdup((char *)export_cred.value); + } + client->store.envval = strdup(p); +#ifdef USE_PAM + if (options.use_pam) + do_pam_putenv(client->store.envvar, client->store.envval); +#endif + if (strncmp(p, "FILE:", 5) == 0) { + p += 5; + } + if (access(p, R_OK) == 0) { + client->store.filename = strdup(p); + } + gss_release_buffer(&minor_status, &export_cred); +} + +#endif /* GSI */ +#endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/gss-serv-krb5.c openssh-4.3p2-gssapi/gss-serv-krb5.c --- openssh-4.3p2/gss-serv-krb5.c 2005-11-04 22:05:28.000000000 -0600 +++ openssh-4.3p2-gssapi/gss-serv-krb5.c 2006-07-26 15:17:38.000000000 -0500 @@ -40,15 +40,29 @@ #ifdef HEIMDAL # include -#else -# ifdef HAVE_GSSAPI_KRB5 +#elif !defined(MECHGLUE) +# ifdef HAVE_GSSAPI_KRB5_H # include -# elif HAVE_GSSAPI_GSSAPI_KRB5 +# elif HAVE_GSSAPI_GSSAPI_KRB5_H # include # endif #endif static krb5_context krb_context = NULL; +static int ssh_gssapi_krb5_init(); +static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", + {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, + NULL, + &ssh_gssapi_krb5_userok, + &ssh_gssapi_krb5_localname, + &ssh_gssapi_krb5_storecreds +}; /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ @@ -101,6 +115,35 @@ } +/* Retrieve the local username associated with a set of Kerberos + * credentials. Hopefully we can use this for the 'empty' username + * logins discussed in the draft */ +static int +ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user) { + krb5_principal princ; + int retval; + + if (ssh_gssapi_krb5_init() == 0) + return 0; + + if ((retval=krb5_parse_name(krb_context, client->displayname.value, + &princ))) { + logit("krb5_parse_name(): %.100s", + krb5_get_err_text(krb_context,retval)); + return 0; + } + + /* We've got to return a malloc'd string */ + *user = (char *)xmalloc(256); + if (krb5_aname_to_localname(krb_context, princ, 256, *user)) { + xfree(*user); + *user = NULL; + return(0); + } + + return(1); +} + /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ @@ -111,6 +154,7 @@ krb5_error_code problem; krb5_principal princ; OM_uint32 maj_status, min_status; + gss_cred_id_t krb5_cred_handle; int len; if (client->creds == NULL) { @@ -153,8 +197,16 @@ krb5_free_principal(krb_context, princ); - if ((maj_status = gss_krb5_copy_ccache(&min_status, - client->creds, ccache))) { +#ifdef MECHGLUE + krb5_cred_handle = + __gss_get_mechanism_cred(client->creds, + &(gssapi_kerberos_mech.oid)); +#else + krb5_cred_handle = client->creds; +#endif + + if ((maj_status = gss_krb5_copy_ccache(&min_status, + krb5_cred_handle, ccache))) { logit("gss_krb5_copy_ccache() failed"); krb5_cc_destroy(krb_context, ccache); return; @@ -176,16 +228,6 @@ return; } -ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", - {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, - NULL, - &ssh_gssapi_krb5_userok, - NULL, - &ssh_gssapi_krb5_storecreds -}; - #endif /* KRB5 */ #endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/HPN12-README openssh-4.3p2-gssapi/HPN12-README --- openssh-4.3p2/HPN12-README 1969-12-31 18:00:00.000000000 -0600 +++ openssh-4.3p2-gssapi/HPN12-README 2006-07-26 15:17:38.000000000 -0500 @@ -0,0 +1,43 @@ +config options + +TcpRcvBuf=[int]KB client + set the TCP socket receive buffer to n Kilobytes. It can be set up to the +maximum socket size allowed by the system. This is useful in situations where +the tcp receive window is set low but the maximum buffer size is set +higher (as is typical). This works on a per TCP connection basis. You can also +use this to artifically limit the transfer rate of the connection. In these +cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. +Default is the current system wide tcp receive buffer size. + +TcpRcvBufPoll=[yes/no] client/server + enable of disable the polling of the tcp receive buffer through the life +of the connection. You would want to make sure that this option is enabled +for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) +default is no. + +NoneEnabled=[yes/no] client/server + enable or disable the use of the None cipher. Care must always be used +when enabling this as it will allow users to send data in the clear. However, +it is important to note that authentication information remains encrypted +even if this option is enabled. Set to no by default. + +NoneSwitch=[yes/no] client + Switch the encryption cipher being used to the None cipher after +authentication takes place. NoneEnabled must be enabled on both the client +and server side of the connection. When the connection switches to the NONE +cipher a warning is sent to STDERR. The connection attempt will fail with an +error if a client requests a NoneSwitch from the server that does not explicitly +have NoneEnabled set to yes. Note: The NONE cipher cannot be used in +interactive (shell) sessions and it will fail silently. Set to no by default. + +HPNDisabled=[yes/no] client/server + In some situations, such as transfers on a local area network, the impact +of the HPN code produces a net decrease in performance. In these cases it is +helpful to disable the HPN functionality. By default HPNDisabled is set to no. + +HPNBufferSize=[int]KB client/server + This is the default buffer size the HPN functionality uses when interacting +with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf +option as applied to the internal SSH flow control. This value can range from +1KB to 14MB (1-14336). Use of oversized or undersized buffers can cause performance +problems depending on the length of the network path. The default size of this buffer diff -Naur --exclude=autom4te.cache openssh-4.3p2/kex.c openssh-4.3p2-gssapi/kex.c --- openssh-4.3p2/kex.c 2005-11-04 22:19:36.000000000 -0600 +++ openssh-4.3p2-gssapi/kex.c 2006-07-26 15:17:38.000000000 -0500 @@ -42,6 +42,10 @@ #include "dispatch.h" #include "monitor.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif + #define KEX_COOKIE_LEN 16 /* prototype */ @@ -49,7 +53,7 @@ static void kex_choose_conf(Kex *); /* put algorithm proposal into buffer */ -static void +void kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) { u_int i; @@ -301,6 +305,16 @@ } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { k->kex_type = KEX_DH_GEX_SHA1; k->evp_md = EVP_sha1(); +#ifdef GSSAPI + } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, + sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) { + k->kex_type = KEX_GSS_GEX_SHA1; + k->evp_md = EVP_sha1(); + } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, + sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) { + k->kex_type = KEX_GSS_GRP1_SHA1; + k->evp_md = EVP_sha1(); +#endif } else fatal("bad kex alg %s", k->name); } diff -Naur --exclude=autom4te.cache openssh-4.3p2/kexgssc.c openssh-4.3p2-gssapi/kexgssc.c --- openssh-4.3p2/kexgssc.c 1969-12-31 18:00:00.000000000 -0600 +++ openssh-4.3p2-gssapi/kexgssc.c 2006-07-26 15:17:38.000000000 -0500 @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef GSSAPI + +#include +#include + +#include "xmalloc.h" +#include "buffer.h" +#include "bufaux.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "dh.h" +#include "canohost.h" +#include "ssh2.h" +#include "ssh-gss.h" + +void +kexgss_client(Kex *kex) { + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; + Gssctxt *ctxt; + OM_uint32 maj_status, min_status, ret_flags; + u_int klen, kout, slen = 0, hashlen, strlen; + DH *dh; + BIGNUM *dh_server_pub = NULL; + BIGNUM *shared_secret = NULL; + BIGNUM *p = NULL; + BIGNUM *g = NULL; + u_char *kbuf, *hash; + u_char *serverhostkey = NULL; + char *msg; + char *lang; + int type = 0; + int first = 1; + int gex = 0; + int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; + + /* Initialise our GSSAPI world */ + ssh_gssapi_build_ctx(&ctxt); + if (ssh_gssapi_id_kex(ctxt, kex->name, &gex) == NULL) + fatal("Couldn't identify host exchange"); + + if (ssh_gssapi_import_name(ctxt, kex->gss_host)) + fatal("Couldn't import hostname"); + + if (gex) { + debug("Doing group exchange\n"); + nbits = dh_estimate(kex->we_need * 8); + packet_start(SSH2_MSG_KEXGSS_GROUPREQ); + packet_put_int(min); + packet_put_int(nbits); + packet_put_int(max); + + packet_send(); + + packet_read_expect(SSH2_MSG_KEXGSS_GROUP); + + if ((p = BN_new()) == NULL) + fatal("BN_new() failed"); + packet_get_bignum2(p); + if ((g = BN_new()) == NULL) + fatal("BN_new() failed"); + packet_get_bignum2(g); + packet_check_eom(); + + if (BN_num_bits(p) < min || BN_num_bits(p) > max) + fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", + min, BN_num_bits(p), max); + + dh = dh_new_group(g, p); + } else { + dh = dh_new_group1(); + } + + /* Step 1 - e is dh->pub_key */ + dh_gen_key(dh, kex->we_need * 8); + + /* This is f, we initialise it now to make life easier */ + dh_server_pub = BN_new(); + if (dh_server_pub == NULL) + fatal("dh_server_pub == NULL"); + + token_ptr = GSS_C_NO_BUFFER; + + do { + debug("Calling gss_init_sec_context"); + + maj_status = ssh_gssapi_init_ctx(ctxt, + kex->gss_deleg_creds, token_ptr, &send_tok, + &ret_flags); + + if (GSS_ERROR(maj_status)) { + if (send_tok.length != 0) { + packet_start(SSH2_MSG_KEXGSS_CONTINUE); + packet_put_string(send_tok.value, + send_tok.length); + } + fatal("gss_init_context failed"); + } + + /* If we've got an old receive buffer get rid of it */ + if (token_ptr != GSS_C_NO_BUFFER) + xfree(recv_tok.value); + + if (maj_status == GSS_S_COMPLETE) { + /* If mutual state flag is not true, kex fails */ + if (!(ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual authentication failed"); + + /* If integ avail flag is not true kex fails */ + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity check failed"); + } + + /* + * If we have data to send, then the last message that we + * received cannot have been a 'complete'. + */ + if (send_tok.length != 0) { + if (first) { + packet_start(SSH2_MSG_KEXGSS_INIT); + packet_put_string(send_tok.value, + send_tok.length); + packet_put_bignum2(dh->pub_key); + first = 0; + } else { + packet_start(SSH2_MSG_KEXGSS_CONTINUE); + packet_put_string(send_tok.value, + send_tok.length); + } + packet_send(); + gss_release_buffer(&min_status, &send_tok); + + /* If we've sent them data, they should reply */ + do { + type = packet_read(); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { + debug("Received KEXGSS_HOSTKEY"); + if (serverhostkey) + fatal("Server host key received more than once"); + serverhostkey = + packet_get_string(&slen); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + + switch (type) { + case SSH2_MSG_KEXGSS_CONTINUE: + debug("Received GSSAPI_CONTINUE"); + if (maj_status == GSS_S_COMPLETE) + fatal("GSSAPI Continue received from server when complete"); + recv_tok.value = packet_get_string(&strlen); + recv_tok.length = strlen; + break; + case SSH2_MSG_KEXGSS_COMPLETE: + debug("Received GSSAPI_COMPLETE"); + packet_get_bignum2(dh_server_pub); + msg_tok.value = packet_get_string(&strlen); + msg_tok.length = strlen; + + /* Is there a token included? */ + if (packet_get_char()) { + recv_tok.value= + packet_get_string(&strlen); + recv_tok.length = strlen; + /* If we're already complete - protocol error */ + if (maj_status == GSS_S_COMPLETE) + packet_disconnect("Protocol error: received token when complete"); + } else { + /* No token included */ + if (maj_status != GSS_S_COMPLETE) + packet_disconnect("Protocol error: did not receive final token"); + } + break; + case SSH2_MSG_KEXGSS_ERROR: + debug("Received Error"); + maj_status = packet_get_int(); + min_status = packet_get_int(); + msg = packet_get_string(NULL); + lang = packet_get_string(NULL); + fatal("GSSAPI Key Exchange Error: \n%s",msg); + default: + packet_disconnect("Protocol error: didn't expect packet type %d", + type); + } + token_ptr = &recv_tok; + } else { + /* No data, and not complete */ + if (maj_status != GSS_S_COMPLETE) + fatal("Not complete, and no token output"); + } + } while (maj_status & GSS_S_CONTINUE_NEEDED); + + /* + * We _must_ have received a COMPLETE message in reply from the + * server, which will have set dh_server_pub and msg_tok + */ + + if (type != SSH2_MSG_KEXGSS_COMPLETE) + fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); + + /* Check f in range [1, p-1] */ + if (!dh_pub_is_valid(dh, dh_server_pub)) + packet_disconnect("bad server public DH value"); + + /* compute K=f^x mod p */ + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_server_pub, dh); + + shared_secret = BN_new(); + BN_bin2bn(kbuf,kout, shared_secret); + memset(kbuf, 0, klen); + xfree(kbuf); + + if (gex) { + kexgex_hash( + kex->evp_md, + kex->client_version_string, + kex->server_version_string, + buffer_ptr(&kex->my), buffer_len(&kex->my), + buffer_ptr(&kex->peer), buffer_len(&kex->peer), + serverhostkey, slen, + min, nbits, max, + dh->p, dh->g, + dh->pub_key, + dh_server_pub, + shared_secret, + &hash, &hashlen + ); + } else { + /* The GSS hash is identical to the DH one */ + kex_dh_hash( kex->client_version_string, + kex->server_version_string, + buffer_ptr(&kex->my), buffer_len(&kex->my), + buffer_ptr(&kex->peer), buffer_len(&kex->peer), + serverhostkey, slen, /* server host key */ + dh->pub_key, /* e */ + dh_server_pub, /* f */ + shared_secret, /* K */ + &hash, &hashlen + ); + } + + gssbuf.value = hash; + gssbuf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ + if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) + packet_disconnect("Hash's MIC didn't verify"); + + xfree(msg_tok.value); + + DH_free(dh); + if (serverhostkey) + xfree(serverhostkey); + BN_clear_free(dh_server_pub); + + /* save session id */ + if (kex->session_id == NULL) { + kex->session_id_len = hashlen; + kex->session_id = xmalloc(kex->session_id_len); + memcpy(kex->session_id, hash, kex->session_id_len); + } + + if (gss_kex_context == NULL) + gss_kex_context = ctxt; + else + ssh_gssapi_delete_ctx(&ctxt); + + kex_derive_keys(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); + kex_finish(kex); +} + +#endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/kexgsss.c openssh-4.3p2-gssapi/kexgsss.c --- openssh-4.3p2/kexgsss.c 1969-12-31 18:00:00.000000000 -0600 +++ openssh-4.3p2-gssapi/kexgsss.c 2006-07-26 15:17:38.000000000 -0500 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef GSSAPI + +#include +#include + +#include "xmalloc.h" +#include "buffer.h" +#include "bufaux.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "dh.h" +#include "ssh2.h" +#include "ssh-gss.h" +#include "monitor_wrap.h" + +static void kex_gss_send_error(Gssctxt *ctxt); + +void +kexgss_server(Kex *kex) +{ + OM_uint32 maj_status, min_status; + + /* + * Some GSSAPI implementations use the input value of ret_flags (an + * output variable) as a means of triggering mechanism specific + * features. Initializing it to zero avoids inadvertently + * activating this non-standard behaviour. + */ + + OM_uint32 ret_flags = 0; + gss_buffer_desc gssbuf, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; + u_int slen, klen, kout, hashlen; + u_char *kbuf, *hash; + DH *dh; + int min = -1, max = -1, nbits = -1; + BIGNUM *shared_secret = NULL; + BIGNUM *dh_client_pub = NULL; + int type = 0; + int gex; + gss_OID oid; + + /* Initialise GSSAPI */ + + /* If we're rekeying, privsep means that some of the private structures + * in the GSSAPI code are no longer available. This kludges them back + * into life + */ + if (!ssh_gssapi_oid_table_ok()) + ssh_gssapi_server_mechanisms(); + + debug2("%s: Identifying %s", __func__, kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, &gex); + if (oid == NULL) + fatal("Unknown gssapi mechanism"); + + debug2("%s: Acquiring credentials", __func__); + + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) { + kex_gss_send_error(ctxt); + fatal("Unable to acquire credentials for the server"); + } + + if (gex) { + debug("Doing group exchange"); + packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); + min = packet_get_int(); + nbits = packet_get_int(); + max = packet_get_int(); + min = MAX(DH_GRP_MIN, min); + max = MIN(DH_GRP_MAX, max); + packet_check_eom(); + if (max < min || nbits < min || max < nbits) + fatal("GSS_GEX, bad parameters: %d !< %d !< %d", + min, nbits, max); + dh = PRIVSEP(choose_dh(min, nbits, max)); + if (dh == NULL) + packet_disconnect("Protocol error: no matching group found"); + + packet_start(SSH2_MSG_KEXGSS_GROUP); + packet_put_bignum2(dh->p); + packet_put_bignum2(dh->g); + packet_send(); + + packet_write_wait(); + + } else { + dh = dh_new_group1(); + } + dh_gen_key(dh, kex->we_need * 8); + + do { + debug("Wait SSH2_MSG_GSSAPI_INIT"); + type = packet_read(); + switch(type) { + case SSH2_MSG_KEXGSS_INIT: + if (dh_client_pub != NULL) + fatal("Received KEXGSS_INIT after initialising"); + recv_tok.value = packet_get_string(&slen); + recv_tok.length = slen; + + if ((dh_client_pub = BN_new()) == NULL) + fatal("dh_client_pub == NULL"); + + packet_get_bignum2(dh_client_pub); + + /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ + break; + case SSH2_MSG_KEXGSS_CONTINUE: + recv_tok.value = packet_get_string(&slen); + recv_tok.length = slen; + break; + default: + packet_disconnect( + "Protocol error: didn't expect packet type %d", + type); + } + + maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, + &send_tok, &ret_flags)); + + xfree(recv_tok.value); + + if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) + fatal("Zero length token output when incomplete"); + + if (dh_client_pub == NULL) + fatal("No client public key"); + + if (maj_status & GSS_S_CONTINUE_NEEDED) { + debug("Sending GSSAPI_CONTINUE"); + packet_start(SSH2_MSG_KEXGSS_CONTINUE); + packet_put_string(send_tok.value, send_tok.length); + packet_send(); + gss_release_buffer(&min_status, &send_tok); + } + } while (maj_status & GSS_S_CONTINUE_NEEDED); + + if (GSS_ERROR(maj_status)) { + kex_gss_send_error(ctxt); + if (send_tok.length > 0) { + packet_start(SSH2_MSG_KEXGSS_CONTINUE); + packet_put_string(send_tok.value, send_tok.length); + packet_send(); + } + packet_disconnect("GSSAPI Key Exchange handshake failed"); + } + + if (!(ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + + if (!dh_pub_is_valid(dh, dh_client_pub)) + packet_disconnect("bad client public DH value"); + + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_client_pub, dh); + + shared_secret = BN_new(); + BN_bin2bn(kbuf, kout, shared_secret); + memset(kbuf, 0, klen); + xfree(kbuf); + + if (gex) { + kexgex_hash( + kex->evp_md, + kex->client_version_string, kex->server_version_string, + buffer_ptr(&kex->peer), buffer_len(&kex->peer), + buffer_ptr(&kex->my), buffer_len(&kex->my), + NULL, 0, + min, nbits, max, + dh->p, dh->g, + dh_client_pub, + dh->pub_key, + shared_secret, + &hash, &hashlen + ); + } + else { + /* The GSSAPI hash is identical to the Diffie Helman one */ + kex_dh_hash( + kex->client_version_string, kex->server_version_string, + buffer_ptr(&kex->peer), buffer_len(&kex->peer), + buffer_ptr(&kex->my), buffer_len(&kex->my), + NULL, 0, /* Change this if we start sending host keys */ + dh_client_pub, dh->pub_key, shared_secret, + &hash, &hashlen + ); + } + BN_free(dh_client_pub); + + if (kex->session_id == NULL) { + kex->session_id_len = hashlen; + kex->session_id = xmalloc(kex->session_id_len); + memcpy(kex->session_id, hash, kex->session_id_len); + } + + gssbuf.value = hash; + gssbuf.length = hashlen; + + if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) + fatal("Couldn't get MIC"); + + packet_start(SSH2_MSG_KEXGSS_COMPLETE); + packet_put_bignum2(dh->pub_key); + packet_put_string((char *)msg_tok.value,msg_tok.length); + + if (send_tok.length != 0) { + packet_put_char(1); /* true */ + packet_put_string((char *)send_tok.value, send_tok.length); + } else { + packet_put_char(0); /* false */ + } + packet_send(); + + gss_release_buffer(&min_status, &send_tok); + gss_release_buffer(&min_status, &msg_tok); + + if (gss_kex_context == NULL) + gss_kex_context = ctxt; + else + ssh_gssapi_delete_ctx(&ctxt); + + DH_free(dh); + + kex_derive_keys(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); + kex_finish(kex); +} + +static void +kex_gss_send_error(Gssctxt *ctxt) { + char *errstr; + OM_uint32 maj,min; + + errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min)); + if (errstr) { + packet_start(SSH2_MSG_KEXGSS_ERROR); + packet_put_int(maj); + packet_put_int(min); + packet_put_cstring(errstr); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); + /* XXX - We should probably log the error locally here */ + xfree(errstr); + } +} +#endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/kex.h openssh-4.3p2-gssapi/kex.h --- openssh-4.3p2/kex.h 2005-11-04 22:19:36.000000000 -0600 +++ openssh-4.3p2-gssapi/kex.h 2006-07-26 15:17:38.000000000 -0500 @@ -63,6 +63,8 @@ KEX_DH_GRP1_SHA1, KEX_DH_GRP14_SHA1, KEX_DH_GEX_SHA1, + KEX_GSS_GRP1_SHA1, + KEX_GSS_GEX_SHA1, KEX_MAX }; @@ -101,6 +103,7 @@ Mac mac; Comp comp; }; + struct Kex { u_char *session_id; u_int session_id_len; @@ -115,6 +118,11 @@ int done; int flags; const EVP_MD *evp_md; +#ifdef GSSAPI + int gss_deleg_creds; + int gss_trust_dns; + char *gss_host; +#endif char *client_version_string; char *server_version_string; int (*verify_host_key)(Key *); @@ -123,6 +131,8 @@ void (*kex[KEX_MAX])(Kex *); }; +void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]); + Kex *kex_setup(char *[PROPOSAL_MAX]); void kex_finish(Kex *); @@ -137,6 +147,11 @@ void kexgex_client(Kex *); void kexgex_server(Kex *); +#ifdef GSSAPI +void kexgss_client(Kex *); +void kexgss_server(Kex *); +#endif + void kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); diff -Naur --exclude=autom4te.cache openssh-4.3p2/key.c openssh-4.3p2-gssapi/key.c --- openssh-4.3p2/key.c 2005-06-16 21:59:35.000000000 -0500 +++ openssh-4.3p2-gssapi/key.c 2006-07-26 15:17:38.000000000 -0500 @@ -650,6 +650,8 @@ return KEY_RSA; } else if (strcmp(name, "ssh-dss") == 0) { return KEY_DSA; + } else if (strcmp(name, "null") == 0) { + return KEY_NULL; } debug2("key_type_from_name: unknown key type '%s'", name); return KEY_UNSPEC; diff -Naur --exclude=autom4te.cache openssh-4.3p2/key.h openssh-4.3p2-gssapi/key.h --- openssh-4.3p2/key.h 2003-11-17 04:18:23.000000000 -0600 +++ openssh-4.3p2-gssapi/key.h 2006-07-26 15:17:38.000000000 -0500 @@ -34,6 +34,7 @@ KEY_RSA1, KEY_RSA, KEY_DSA, + KEY_NULL, KEY_UNSPEC }; enum fp_type { diff -Naur --exclude=autom4te.cache openssh-4.3p2/Makefile.in openssh-4.3p2-gssapi/Makefile.in --- openssh-4.3p2/Makefile.in 2006-01-01 02:47:05.000000000 -0600 +++ openssh-4.3p2-gssapi/Makefile.in 2006-07-26 15:17:38.000000000 -0500 @@ -59,6 +59,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ +INSTALL_GSISSH=@INSTALL_GSISSH@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) @@ -71,7 +72,7 @@ atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ - entropy.o scard-opensc.o gss-genr.o + entropy.o scard-opensc.o gss-genr.o kexgssc.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o @@ -84,7 +85,8 @@ auth2-none.o auth2-passwd.o auth2-pubkey.o \ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \ auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + gss-serv-gsi.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ audit.o audit-bsm.o @@ -282,6 +284,20 @@ ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(bindir)/gsissh; \ + ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/gsissh; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + rm -f $(DESTDIR)$(bindir)/gsiscp; \ + ln -s ./scp$(EXEEXT) $(DESTDIR)$(bindir)/gsiscp; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + ln -s ./scp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + rm -f $(DESTDIR)$(bindir)/gsisftp; \ + ln -s ./sftp$(EXEEXT) $(DESTDIR)$(bindir)/gsisftp; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + ln -s ./sftp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + fi install-sysconf: if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ @@ -353,6 +369,11 @@ uninstall: -rm -f $(DESTDIR)$(bindir)/slogin + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(bindir)/gsiscp; \ + rm -f $(DESTDIR)$(bindir)/gsissh; \ + rm -f $(DESTDIR)$(bindir)/gsisftp; \ + fi -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) @@ -366,6 +387,11 @@ -rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + fi -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 diff -Naur --exclude=autom4te.cache openssh-4.3p2/misc.c openssh-4.3p2-gssapi/misc.c --- openssh-4.3p2/misc.c 2006-01-31 04:49:28.000000000 -0600 +++ openssh-4.3p2-gssapi/misc.c 2006-07-26 15:17:38.000000000 -0500 @@ -124,11 +124,14 @@ /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" +/* Characters considered as quotations. */ +#define QUOTES "'\"" + /* return next token in configuration line */ char * strdelim(char **s) { - char *old; + char *old, *p, *q; int wspace = 0; if (*s == NULL) @@ -136,7 +139,22 @@ old = *s; - *s = strpbrk(*s, WHITESPACE "="); + if ((q=strchr(QUOTES, (int) *old)) && *q) + { + /* find next quote character, point old to start of quoted + * string */ + for (p = ++old;*p && *p!=*q; p++) + ; + + /* find start of next token */ + *s = (*p) ? p + strspn(p + 1, WHITESPACE) + 1 : NULL; + + /* terminate 'old' token */ + *p = '\0'; + return (old); + } + + *s = strpbrk(*s, WHITESPACE "="); if (*s == NULL) return (old); diff -Naur --exclude=autom4te.cache openssh-4.3p2/monitor.c openssh-4.3p2-gssapi/monitor.c --- openssh-4.3p2/monitor.c 2005-11-04 22:07:05.000000000 -0600 +++ openssh-4.3p2-gssapi/monitor.c 2006-07-26 15:17:38.000000000 -0500 @@ -141,6 +141,10 @@ int mm_answer_gss_accept_ctx(int, Buffer *); int mm_answer_gss_userok(int, Buffer *); int mm_answer_gss_checkmic(int, Buffer *); +int mm_answer_gss_sign(int, Buffer *); +int mm_answer_gss_error(int, Buffer *); +int mm_answer_gss_indicate_mechs(int, Buffer *); +int mm_answer_gss_localname(int, Buffer *); #endif #ifdef SSH_AUDIT_EVENTS @@ -179,12 +183,12 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_PWNAM, MON_AUTH, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start}, {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, @@ -209,11 +213,22 @@ {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, + {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname}, #endif {0, 0, NULL} }; struct mon_table mon_dispatch_postauth20[] = { +#ifdef GSSAPI + {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, + {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error}, + {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, +#endif {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, @@ -243,8 +258,15 @@ {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, #endif +#ifdef GSSAPI + {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, +#endif #ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start}, {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, @@ -318,6 +340,12 @@ /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); +#ifdef GSSAPI + /* and for the GSSAPI key exchange */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1); +#endif } else { mon_dispatch = mon_dispatch_proto15; @@ -391,10 +419,21 @@ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + +#ifdef GSSAPI + /* and for the GSSAPI key exchange */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1); +#endif + } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); } +#ifdef GSSAPI + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1); +#endif if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); @@ -579,13 +618,11 @@ debug3("%s", __func__); - if (authctxt->attempt++ != 0) - fatal("%s: multiple attempts for getpwnam", __func__); - username = buffer_get_string(m, NULL); pwent = getpwnamallow(username); + if (authctxt->user) xfree(authctxt->user); authctxt->user = xstrdup(username); setproctitle("%s [priv]", pwent ? username : "unknown"); xfree(username); @@ -1621,6 +1658,10 @@ kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; +#ifdef GSSAPI + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; +#endif kex->server = 1; kex->hostkey_type = buffer_get_int(m); kex->kex_type = buffer_get_int(m); @@ -1862,7 +1903,9 @@ if (major == GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); } return (0); } @@ -1913,4 +1956,106 @@ /* Monitor loop will terminate if authenticated */ return (authenticated); } + +int +mm_answer_gss_sign(int socket, Buffer *m) +{ + gss_buffer_desc data; + gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + u_int len; + + data.value = buffer_get_string(m, &len); + data.length = len; + if (data.length != 20) + fatal("%s: data length incorrect: %d", __func__, data.length); + + /* Save the session ID on the first time around */ + if (session_id2_len == 0) { + session_id2_len = data.length; + session_id2 = xmalloc(session_id2_len); + memcpy(session_id2, data.value, session_id2_len); + } + major = ssh_gssapi_sign(gsscontext, &data, &hash); + + xfree(data.value); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_string(m, hash.value, hash.length); + + mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); + + gss_release_buffer(&minor, &hash); + + /* Turn on getpwnam permissions */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); + + return (0); +} + +int +mm_answer_gss_error(int socket, Buffer *m) { + OM_uint32 major,minor; + char *msg; + + msg=ssh_gssapi_last_error(gsscontext,&major,&minor); + buffer_clear(m); + buffer_put_int(m,major); + buffer_put_int(m,minor); + buffer_put_cstring(m,msg); + + mm_request_send(socket,MONITOR_ANS_GSSERR,m); + + xfree(msg); + + return(0); +} + +int +mm_answer_gss_indicate_mechs(int socket, Buffer *m) { + OM_uint32 major,minor; + gss_OID_set mech_set; + size_t i; + + major=gss_indicate_mechs(&minor, &mech_set); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_int(m, mech_set->count); + for (i=0; i < mech_set->count; i++) { + buffer_put_string(m, mech_set->elements[i].elements, + mech_set->elements[i].length); + } + +#if !defined(MECHGLUE) /* mechglue memory management bug ??? */ + gss_release_oid_set(&minor,&mech_set); +#endif + + mm_request_send(socket,MONITOR_ANS_GSSMECHS,m); + + return(0); +} + +int +mm_answer_gss_localname(int socket, Buffer *m) { + char *name; + + ssh_gssapi_localname(&name); + + buffer_clear(m); + if (name) { + buffer_put_cstring(m, name); + debug3("%s: sending result %s", __func__, name); + xfree(name); + } else { + buffer_put_cstring(m, ""); + debug3("%s: sending result \"\"", __func__); + } + + mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m); + + return(0); +} + #endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/monitor.h openssh-4.3p2-gssapi/monitor.h --- openssh-4.3p2/monitor.h 2005-02-02 07:20:53.000000000 -0600 +++ openssh-4.3p2-gssapi/monitor.h 2006-07-26 15:17:38.000000000 -0500 @@ -52,7 +52,11 @@ MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP, MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, + MONITOR_REQ_GSSMECHS, MONITOR_ANS_GSSMECHS, + MONITOR_REQ_GSSLOCALNAME, MONITOR_ANS_GSSLOCALNAME, + MONITOR_REQ_GSSERR, MONITOR_ANS_GSSERR, MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, + MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, MONITOR_REQ_PAM_START, MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, diff -Naur --exclude=autom4te.cache openssh-4.3p2/monitor_wrap.c openssh-4.3p2-gssapi/monitor_wrap.c --- openssh-4.3p2/monitor_wrap.c 2005-09-29 07:01:10.000000000 -0500 +++ openssh-4.3p2-gssapi/monitor_wrap.c 2006-07-26 15:17:38.000000000 -0500 @@ -1215,4 +1215,104 @@ debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); return (authenticated); } + +OM_uint32 +mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) +{ + Buffer m; + OM_uint32 major; + u_int len; + + buffer_init(&m); + buffer_put_string(&m, data->value, data->length); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); + + major = buffer_get_int(&m); + hash->value = buffer_get_string(&m, &len); + hash->length = len; + + buffer_free(&m); + + return(major); +} + +char * +mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) { + Buffer m; + OM_uint32 maj,min; + char *errstr; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m); + + maj = buffer_get_int(&m); + min = buffer_get_int(&m); + + if (major) *major=maj; + if (minor) *minor=min; + + errstr=buffer_get_string(&m,NULL); + + buffer_free(&m); + + return(errstr); +} + +OM_uint32 +mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set) +{ + Buffer m; + OM_uint32 major,minor; + int count; + gss_OID_desc oid; + u_int length; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS, + &m); + major=buffer_get_int(&m); + count=buffer_get_int(&m); + + gss_create_empty_oid_set(&minor,mech_set); + while(count-->0) { + oid.elements=buffer_get_string(&m,&length); + oid.length=length; + gss_add_oid_set_member(&minor,&oid,mech_set); + } + + buffer_free(&m); + + return(major); +} + +int +mm_ssh_gssapi_localname(char **lname) +{ + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m); + + debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME, + &m); + + *lname = buffer_get_string(&m, NULL); + + buffer_free(&m); + if (lname[0] == '\0') { + debug3("%s: gssapi identity mapping failed", __func__); + } else { + debug3("%s: gssapi identity mapped to %s", __func__, *lname); + } + + return(0); +} + #endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/monitor_wrap.h openssh-4.3p2-gssapi/monitor_wrap.h --- openssh-4.3p2/monitor_wrap.h 2005-02-08 04:52:48.000000000 -0600 +++ openssh-4.3p2-gssapi/monitor_wrap.h 2006-07-26 15:17:38.000000000 -0500 @@ -63,6 +63,11 @@ gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); int mm_ssh_gssapi_userok(char *user); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); +OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); +int mm_ssh_gssapi_localname(char **user); +OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set); +char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min); #endif #ifdef USE_PAM diff -Naur --exclude=autom4te.cache openssh-4.3p2/myproposal.h openssh-4.3p2-gssapi/myproposal.h --- openssh-4.3p2/myproposal.h 2005-07-26 06:54:56.000000000 -0500 +++ openssh-4.3p2-gssapi/myproposal.h 2006-07-26 15:17:38.000000000 -0500 @@ -32,6 +32,8 @@ "arcfour128,arcfour256,arcfour," \ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ "aes128-ctr,aes192-ctr,aes256-ctr" +#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \ + ",none" #define KEX_DEFAULT_MAC \ "hmac-md5,hmac-sha1,hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ diff -Naur --exclude=autom4te.cache openssh-4.3p2/openbsd-compat/port-aix.h openssh-4.3p2-gssapi/openbsd-compat/port-aix.h --- openssh-4.3p2/openbsd-compat/port-aix.h 2005-05-28 05:28:40.000000000 -0500 +++ openssh-4.3p2-gssapi/openbsd-compat/port-aix.h 2006-07-26 15:17:38.000000000 -0500 @@ -39,6 +39,7 @@ # include # include # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG) +# undef T_NULL # include # endif # include diff -Naur --exclude=autom4te.cache openssh-4.3p2/packet.c openssh-4.3p2-gssapi/packet.c --- openssh-4.3p2/packet.c 2005-11-04 22:15:00.000000000 -0600 +++ openssh-4.3p2-gssapi/packet.c 2006-07-26 15:17:38.000000000 -0500 @@ -1546,6 +1546,13 @@ rnd >>= 8; } } +int rekey_requested = 0; + +void +packet_request_rekeying(void) +{ + rekey_requested = 1; +} #define MAX_PACKETS (1U<<31) int @@ -1553,6 +1560,11 @@ { if (datafellows & SSH_BUG_NOREKEY) return 0; + if (rekey_requested == 1) + { + rekey_requested = 0; + return 1; + } return (p_send.packets > MAX_PACKETS) || (p_read.packets > MAX_PACKETS) || diff -Naur --exclude=autom4te.cache openssh-4.3p2/packet.h openssh-4.3p2-gssapi/packet.h --- openssh-4.3p2/packet.h 2005-07-26 06:54:56.000000000 -0500 +++ openssh-4.3p2-gssapi/packet.h 2006-07-26 15:17:38.000000000 -0500 @@ -18,6 +18,9 @@ #include +void +packet_request_rekeying(void); + void packet_set_connection(int, int); void packet_set_nonblocking(void); int packet_get_connection_in(void); diff -Naur --exclude=autom4te.cache openssh-4.3p2/readconf.c openssh-4.3p2-gssapi/readconf.c --- openssh-4.3p2/readconf.c 2005-12-13 02:33:20.000000000 -0600 +++ openssh-4.3p2-gssapi/readconf.c 2006-07-26 15:17:38.000000000 -0500 @@ -109,9 +109,13 @@ oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, + oGssKeyEx, + oGssTrustDns, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, + oHPNBufferSize, oDeprecated, oUnsupported } OpCodes; @@ -144,10 +148,14 @@ { "afstokenpassing", oUnsupported }, #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, + { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, + { "gssapitrustdns", oGssTrustDns }, #else { "gssapiauthentication", oUnsupported }, + { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, + { "gssapitrustdns", oUnsupported }, #endif { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, @@ -207,6 +215,12 @@ { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, + { "noneenabled", oNoneEnabled }, + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "noneswitch", oNoneSwitch }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, { NULL, oBadOption } }; @@ -416,10 +430,18 @@ intptr = &options->gss_authentication; goto parse_flag; + case oGssKeyEx: + intptr = &options->gss_keyex; + goto parse_flag; + case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; + case oGssTrustDns: + intptr = &options->gss_trust_dns; + goto parse_flag; + case oBatchMode: intptr = &options->batch_mode; goto parse_flag; @@ -428,10 +450,31 @@ intptr = &options->check_host_ip; goto parse_flag; + case oNoneEnabled: + intptr = &options->none_enabled; + goto parse_flag; + + case oNoneSwitch: + intptr = &options->none_switch; + goto parse_flag; + + case oHPNDisabled: + intptr = &options->hpn_disabled; + goto parse_flag; + + case oHPNBufferSize: + intptr = &options->hpn_buffer_size; + goto parse_int; + + case oTcpRcvBufPoll: + intptr = &options->tcp_rcv_buf_poll; + goto parse_flag; + case oVerifyHostKeyDNS: intptr = &options->verify_host_key_dns; goto parse_yesnoask; + case oStrictHostKeyChecking: intptr = &options->strict_host_key_checking; parse_yesnoask: @@ -593,6 +636,10 @@ intptr = &options->connection_attempts; goto parse_int; + case oTcpRcvBuf: + intptr = &options->tcp_rcv_buf; + goto parse_int; + case oCipher: intptr = &options->cipher; arg = strdelim(&s); @@ -970,7 +1017,9 @@ options->pubkey_authentication = -1; options->challenge_response_authentication = -1; options->gss_authentication = -1; + options->gss_keyex = -1; options->gss_deleg_creds = -1; + options->gss_trust_dns = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; @@ -1025,6 +1074,12 @@ options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; } /* @@ -1056,9 +1111,13 @@ if (options->challenge_response_authentication == -1) options->challenge_response_authentication = 1; if (options->gss_authentication == -1) - options->gss_authentication = 0; + options->gss_authentication = 1; + if (options->gss_keyex == -1) + options->gss_keyex = 1; if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; + options->gss_deleg_creds = 1; + if (options->gss_trust_dns == -1) + options->gss_trust_dns = 1; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@ -1145,6 +1204,24 @@ options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; + if (options->none_switch == -1) + options->none_switch = 0; + if (options->hpn_disabled == -1) + options->hpn_disabled = 0; + if (options->hpn_buffer_size == -1) + options->hpn_buffer_size = 2*1024*1024; + else { + if (options->hpn_buffer_size == 0) + options->hpn_buffer_size = 1; + /*limit the buffer to 7MB*/ + if (options->hpn_buffer_size > 7168) + options->hpn_buffer_size = 7168; + options->hpn_buffer_size *=1024; + } + if (options->tcp_rcv_buf == 0) + options->tcp_rcv_buf = 1; + if (options->tcp_rcv_buf > -1) + options->tcp_rcv_buf *=1024; if (options->control_master == -1) options->control_master = 0; if (options->hash_known_hosts == -1) diff -Naur --exclude=autom4te.cache openssh-4.3p2/readconf.h openssh-4.3p2-gssapi/readconf.h --- openssh-4.3p2/readconf.h 2005-12-13 02:29:02.000000000 -0600 +++ openssh-4.3p2-gssapi/readconf.h 2006-07-26 15:17:38.000000000 -0500 @@ -45,7 +45,9 @@ int challenge_response_authentication; /* Try S/Key or TIS, authentication. */ int gss_authentication; /* Try GSS authentication */ + int gss_keyex; int gss_deleg_creds; /* Delegate GSS credentials */ + int gss_trust_dns; /* Trust DNS for GSS canonicalization */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ @@ -57,6 +59,11 @@ int compression_level; /* Compression level 1 (fast) to 9 * (best). */ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ + int tcp_rcv_buf; /* user switch to set tcp recv buffer */ + int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ + int hpn_disabled; /* Switch to disable HPN buffer management */ + int hpn_buffer_size; /* User definable size for HPN buffer window */ + LogLevel log_level; /* Level for logging. */ int port; /* Port to connect. */ @@ -76,6 +83,8 @@ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ char *user; /* User to log in as. */ + int implicit; /* Login user was not specified. + Server may choose based on authctxt. */ int escape_char; /* Escape character; -2 = none */ char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ @@ -102,6 +111,8 @@ int enable_ssh_keysign; int rekey_limit; + int none_switch; /* use none cipher */ + int none_enabled; /* Allow none to be used */ int no_host_authentication_for_localhost; int identities_only; int server_alive_interval; diff -Naur --exclude=autom4te.cache openssh-4.3p2/scp.c openssh-4.3p2-gssapi/scp.c --- openssh-4.3p2/scp.c 2006-01-31 05:11:38.000000000 -0600 +++ openssh-4.3p2-gssapi/scp.c 2006-07-26 15:17:38.000000000 -0500 @@ -278,7 +278,7 @@ addargs(&args, "-oClearAllForwardings yes"); fflag = tflag = 0; - while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) + while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246zS:o:F:w:")) != -1) switch (ch) { /* User-visible flags. */ case '1': @@ -286,6 +286,7 @@ case '4': case '6': case 'C': + case 'z': addargs(&args, "-%c", ch); break; case 'o': @@ -339,6 +340,9 @@ setmode(0, O_BINARY); #endif break; + case 'w': + addargs(&args, "-w%s", optarg); + break; default: usage(); } @@ -553,7 +557,7 @@ off_t i, amt, statbytes; size_t result; int fd = -1, haderr, indx; - char *last, *name, buf[2048]; + char *last, *name, buf[16384]; int len; for (indx = 0; indx < argc; ++indx) { @@ -613,7 +617,7 @@ (void) atomicio(vwrite, remout, buf, strlen(buf)); if (response() < 0) goto next; - if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { + if ((bp = allocbuf(&buffer, fd, sizeof(buf))) == NULL) { next: if (fd != -1) { (void) close(fd); fd = -1; @@ -780,7 +784,7 @@ int amt, exists, first, mask, mode, ofd, omode; off_t size, statbytes; int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; + char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; struct timeval tv[2]; #define atime tv[0] @@ -941,7 +945,7 @@ continue; } (void) atomicio(vwrite, remout, "", 1); - if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { + if ((bp = allocbuf(&buffer, ofd, sizeof(buf))) == NULL) { (void) close(ofd); continue; } @@ -951,8 +955,8 @@ statbytes = 0; if (showprogress) start_progress_meter(curfile, size, &statbytes); - for (count = i = 0; i < size; i += 4096) { - amt = 4096; + for (count = i = 0; i < size; i += sizeof(buf)) { + amt = sizeof(buf); if (i + amt > size) amt = size - i; count += amt; @@ -969,7 +973,7 @@ } while (amt > 0); if (limit_rate) - bwlimit(4096); + bwlimit(sizeof(buf)); if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ @@ -1085,7 +1089,7 @@ { (void) fprintf(stderr, "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" - " [-l limit] [-o ssh_option] [-P port] [-S program]\n" + " [-l limit] [-o ssh_option] [-P port] [-w buffer size] [-S program]\n" " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); exit(1); } diff -Naur --exclude=autom4te.cache openssh-4.3p2/servconf.c openssh-4.3p2-gssapi/servconf.c --- openssh-4.3p2/servconf.c 2005-12-13 02:33:20.000000000 -0600 +++ openssh-4.3p2-gssapi/servconf.c 2006-07-26 15:17:38.000000000 -0500 @@ -70,9 +70,16 @@ options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; +#ifdef SESSION_HOOKS + options->session_hooks_allow = -1; + options->session_hooks_startup_cmd = NULL; + options->session_hooks_shutdown_cmd = NULL; +#endif options->kerberos_get_afs_token = -1; options->gss_authentication=-1; + options->gss_keyex = -1; options->gss_cleanup_creds = -1; + options->gsi_allow_limited_proxy = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@ -102,6 +109,10 @@ options->authorized_keys_file2 = NULL; options->num_accept_env = 0; options->permit_tun = -1; + options->none_enabled = -1; + options->tcp_rcv_buf_poll = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; /* Needs to be accessable in many places */ use_privsep = -1; @@ -110,6 +121,7 @@ void fill_default_server_options(ServerOptions *options) { + /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; @@ -186,9 +198,13 @@ if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) - options->gss_authentication = 0; + options->gss_authentication = 1; + if (options->gss_keyex == -1) + options->gss_keyex = 1; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; + if (options->gsi_allow_limited_proxy == -1) + options->gsi_allow_limited_proxy = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@ -233,10 +249,26 @@ if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; + if (options->hpn_disabled == -1) + options->hpn_disabled = 0; + + if (options->hpn_buffer_size == -1) + options->hpn_buffer_size = 2*1024*1024; + else { + if (options->hpn_buffer_size == 0) + options->hpn_buffer_size = 1; + /* limit the maximum buffer to 7MB */ + if (options->hpn_buffer_size > 7168) + options->hpn_buffer_size = 7168; + options->hpn_buffer_size *=1024; + } + /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = 1; + + #ifndef HAVE_MMAP if (use_privsep && options->compression == 1) { error("This platform does not support both privilege " @@ -260,6 +292,9 @@ sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, sKerberosTgtPassing, sChallengeResponseAuthentication, +#ifdef SESSION_HOOKS + sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd, +#endif sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, @@ -273,8 +308,11 @@ sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sGssKeyEx, + sGsiAllowLimitedProxy, sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, - sUsePrivilegeSeparation, + sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll, + sHPNDisabled, sHPNBufferSize, sDeprecated, sUnsupported } ServerOpCodes; @@ -327,11 +365,21 @@ { "afstokenpassing", sUnsupported }, #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication }, + { "gssapikeyexchange", sGssKeyEx }, { "gssapicleanupcredentials", sGssCleanupCreds }, +#ifdef GSI + { "gsiallowlimitedproxy", sGsiAllowLimitedProxy }, +#endif #else { "gssapiauthentication", sUnsupported }, + { "gssapikeyexchange", sUnsupported }, { "gssapicleanupcredentials", sUnsupported }, #endif +#ifdef SESSION_HOOKS + { "allowsessionhooks", sAllowSessionHooks }, + { "sessionhookstartupcmd", sSessionHookStartupCmd }, + { "sessionhookshutdowncmd", sSessionHookShutdownCmd }, +#endif { "passwordauthentication", sPasswordAuthentication }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, { "challengeresponseauthentication", sChallengeResponseAuthentication }, @@ -376,6 +424,10 @@ { "authorizedkeysfile2", sAuthorizedKeysFile2 }, { "useprivilegeseparation", sUsePrivilegeSeparation}, { "acceptenv", sAcceptEnv }, + { "noneenabled", sNoneEnabled }, + { "hpndisabled", sHPNDisabled }, + { "hpnbuffersize", sHPNBufferSize }, + { "tcprcvbufpoll", sTcpRcvBufPoll }, { "permittunnel", sPermitTunnel }, { NULL, sBadOption } }; @@ -391,9 +443,9 @@ u_int i; for (i = 0; keywords[i].name; i++) - if (strcasecmp(cp, keywords[i].name) == 0) - return keywords[i].opcode; - + if (strcasecmp(cp, keywords[i].name) == 0){ + debug ("TOKEN IS %s", keywords[i].name); + return keywords[i].opcode;} error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); return sBadOption; @@ -457,6 +509,7 @@ intptr = NULL; charptr = NULL; opcode = parse_token(arg, filename, linenum); + switch (opcode) { /* Portable-specific options */ case sUsePAM: @@ -629,6 +682,22 @@ *intptr = value; break; + case sNoneEnabled: + intptr = &options->none_enabled; + goto parse_flag; + + case sTcpRcvBufPoll: + intptr = &options->tcp_rcv_buf_poll; + goto parse_flag; + + case sHPNDisabled: + intptr = &options->hpn_disabled; + goto parse_flag; + + case sHPNBufferSize: + intptr = &options->hpn_buffer_size; + goto parse_int; + case sIgnoreUserKnownHosts: intptr = &options->ignore_user_known_hosts; goto parse_flag; @@ -673,10 +742,35 @@ intptr = &options->gss_authentication; goto parse_flag; + case sGssKeyEx: + intptr = &options->gss_keyex; + goto parse_flag; + case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; + case sGsiAllowLimitedProxy: + intptr = &options->gsi_allow_limited_proxy; + goto parse_flag; + +#ifdef SESSION_HOOKS + case sAllowSessionHooks: + intptr = &options->session_hooks_allow; + goto parse_flag; + case sSessionHookStartupCmd: + case sSessionHookShutdownCmd: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: empty session hook command", + filename, linenum); + if (opcode==sSessionHookStartupCmd) + options->session_hooks_startup_cmd = strdup(arg); + else + options->session_hooks_shutdown_cmd = strdup(arg); + break; +#endif + case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; diff -Naur --exclude=autom4te.cache openssh-4.3p2/servconf.h openssh-4.3p2-gssapi/servconf.h --- openssh-4.3p2/servconf.h 2005-12-13 02:29:03.000000000 -0600 +++ openssh-4.3p2-gssapi/servconf.h 2006-07-26 15:17:38.000000000 -0500 @@ -85,10 +85,17 @@ * /etc/passwd */ int kerberos_ticket_cleanup; /* If true, destroy ticket * file on logout. */ +#ifdef SESSION_HOOKS + int session_hooks_allow; /* If true, permit user hooks */ + char* session_hooks_startup_cmd; /* cmd to be executed before */ + char* session_hooks_shutdown_cmd; /* cmd to be executed after */ +#endif int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ + int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ + int gsi_allow_limited_proxy; /* If true, accept limited proxies */ int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ @@ -135,6 +142,10 @@ char *authorized_keys_file2; int use_pam; /* Enable auth via PAM */ + int none_enabled; /* enable NONE cipher switch */ + int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ + int hpn_disabled; /* disable hpn functionality. false by default */ + int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ int permit_tun; } ServerOptions; diff -Naur --exclude=autom4te.cache openssh-4.3p2/serverloop.c openssh-4.3p2-gssapi/serverloop.c --- openssh-4.3p2/serverloop.c 2005-12-30 23:33:37.000000000 -0600 +++ openssh-4.3p2-gssapi/serverloop.c 2006-07-26 15:17:38.000000000 -0500 @@ -907,9 +907,14 @@ xfree(originator); if (sock < 0) return NULL; - c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING, - sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, - CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1); + if (options.hpn_disabled) + c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING, + sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, + CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1); + else + c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING, + sock, sock, -1, options.hpn_buffer_size, + CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1); return c; } @@ -944,8 +949,12 @@ sock = tun_open(tun, mode); if (sock < 0) goto done; - c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + if (options.hpn_disabled) + c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + else + c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, + options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (mode == SSH_TUNMODE_POINTOPOINT) @@ -975,6 +984,8 @@ c = channel_new("session", SSH_CHANNEL_LARVAL, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, "server-session", 1); + if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) + c->dynamic_window = 1; if (session_open(the_authctxt, c->self) != 1) { debug("session open failed, free channel %d", c->self); channel_free(c); @@ -1071,7 +1082,8 @@ } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener( - listen_address, listen_port, options.gateway_ports); + listen_address, listen_port, options.gateway_ports, + options.hpn_disabled, options.hpn_buffer_size); } xfree(listen_address); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { diff -Naur --exclude=autom4te.cache openssh-4.3p2/session.c openssh-4.3p2-gssapi/session.c --- openssh-4.3p2/session.c 2006-02-07 17:18:55.000000000 -0600 +++ openssh-4.3p2-gssapi/session.c 2006-07-26 15:17:38.000000000 -0500 @@ -90,6 +90,11 @@ static int session_pty_req(Session *); +#ifdef SESSION_HOOKS +static void execute_session_hook(char* prog, Authctxt *authctxt, + int startup, int save); +#endif + /* import */ extern ServerOptions options; extern char *__progname; @@ -186,6 +191,7 @@ packet_disconnect("listen: %.100s", strerror(errno)); /* Allocate a channel for the authentication agent socket. */ + /* this shouldn't matter if its hpn or not - cjr */ nc = channel_new("auth socket", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, @@ -218,6 +224,21 @@ else do_authenticated1(authctxt); +#ifdef SESSION_HOOKS + if (options.session_hooks_allow && + options.session_hooks_shutdown_cmd) + { + execute_session_hook(options.session_hooks_shutdown_cmd, + authctxt, + /* startup = */ 0, /* save = */ 0); + + if (authctxt->session_env_file) + { + free(authctxt->session_env_file); + } + } +#endif + do_cleanup(authctxt); } @@ -322,7 +343,9 @@ break; } debug("Received TCP/IP port forwarding request."); - channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports); + channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports, + options.hpn_disabled, + options.hpn_buffer_size); success = 1; break; @@ -657,6 +680,26 @@ debug("Forced command '%.900s'", command); } +#if defined(SESSION_HOOKS) + if (options.session_hooks_allow && + (options.session_hooks_startup_cmd || + options.session_hooks_shutdown_cmd)) + { + char env_file[1000]; + struct stat st; + do + { + snprintf(env_file, + sizeof(env_file), + "/tmp/ssh_env_%d%d%d", + getuid(), + getpid(), + rand()); + } while (stat(env_file, &st)==0); + s->authctxt->session_env_file = strdup(env_file); + } +#endif + #ifdef SSH_AUDIT_EVENTS if (command != NULL) PRIVSEP(audit_run_command(command)); @@ -883,6 +926,117 @@ fclose(f); } +#ifdef SESSION_HOOKS +#define SSH_SESSION_ENV_FILE "SSH_SESSION_ENV_FILE" + +typedef enum { no_op, execute, clear_env, restore_env, + read_env, save_or_rm_env } session_action_t; + +static session_action_t action_order[2][5] = { + { clear_env, read_env, execute, save_or_rm_env, restore_env }, /*shutdown*/ + { execute, read_env, save_or_rm_env, no_op, no_op } /*startup */ +}; + +static +void execute_session_hook(char* prog, Authctxt *authctxt, + int startup, int save) +{ + extern char **environ; + + struct stat st; + char **saved_env, **tmpenv; + char *env_file = authctxt->session_env_file; + int i, status = 0; + + for (i=0; i<5; i++) + { + switch (action_order[startup][i]) + { + case no_op: + break; + + case execute: + { + FILE* fp; + char buf[1000]; + + snprintf(buf, + sizeof(buf), + "%s -c '%s'", + authctxt->pw->pw_shell, + prog); + + debug("executing session hook: [%s]", buf); + setenv(SSH_SESSION_ENV_FILE, env_file, /* overwrite = */ 1); + + /* flusing is recommended in the popen(3) man page, to avoid + intermingling of output */ + fflush(stdout); + fflush(stderr); + if ((fp=popen(buf, "w")) == NULL) + { + perror("Unable to run session hook"); + return; + } + status = pclose(fp); + debug2("session hook executed, status=%d", status); + unsetenv(SSH_SESSION_ENV_FILE); + } + break; + + case clear_env: + saved_env = environ; + tmpenv = (char**) malloc(sizeof(char*)); + tmpenv[0] = NULL; + environ = tmpenv; + break; + + case restore_env: + environ = saved_env; + free(tmpenv); + break; + + case read_env: + if (status==0 && stat(env_file, &st)==0) + { + int envsize = 0; + + debug("reading environment from %s", env_file); + while (environ[envsize++]) ; + read_environment_file(&environ, &envsize, env_file); + } + break; + + case save_or_rm_env: + if (status==0 && save) + { + FILE* fp; + int envcount=0; + + debug2("saving environment to %s", env_file); + if ((fp = fopen(env_file, "w")) == NULL) /* hmm: file perms? */ + { + perror("Unable to save session hook info"); + } + while (environ[envcount]) + { + fprintf(fp, "%s\n", environ[envcount++]); + } + fflush(fp); + fclose(fp); + } + else if (stat(env_file, &st)==0) + { + debug2("removing environment file %s", env_file); + remove(env_file); + } + break; + } + } + +} +#endif + #ifdef HAVE_ETC_DEFAULT_LOGIN /* * Return named variable from specified environment, or NULL if not present. @@ -1043,6 +1197,23 @@ if (getenv("TZ")) child_set_env(&env, &envsize, "TZ", getenv("TZ")); +#ifdef GSI /* GSI shared libs typically installed in non-system locations. */ + { + char *cp; + + if ((cp = getenv("LD_LIBRARY_PATH")) != NULL) + child_set_env(&env, &envsize, "LD_LIBRARY_PATH", cp); + if ((cp = getenv("LIBPATH")) != NULL) + child_set_env(&env, &envsize, "LIBPATH", cp); + if ((cp = getenv("SHLIB_PATH")) != NULL) + child_set_env(&env, &envsize, "SHLIB_PATH", cp); + if ((cp = getenv("LD_LIBRARYN32_PATH")) != NULL) + child_set_env(&env, &envsize, "LD_LIBRARYN32_PATH",cp); + if ((cp = getenv("LD_LIBRARY64_PATH")) != NULL) + child_set_env(&env, &envsize, "LD_LIBRARY64_PATH",cp); + } +#endif + /* Set custom environment options from RSA authentication. */ if (!options.use_login) { while (custom_environment) { @@ -1433,6 +1604,18 @@ const char *shell, *shell0, *hostname = NULL; struct passwd *pw = s->pw; +#ifdef AFS_KRB5 +/* Default place to look for aklog. */ +#ifdef AKLOG_PATH +#define KPROGDIR AKLOG_PATH +#else +#define KPROGDIR "/usr/bin/aklog" +#endif /* AKLOG_PATH */ + + struct stat st; + char *aklog_path; +#endif /* AFS_KRB5 */ + /* remove hostkey from the child's memory */ destroy_sensitive_data(); @@ -1545,6 +1728,41 @@ } #endif +#ifdef AFS_KRB5 + + /* User has authenticated, and if a ticket was going to be + * passed we would have it. KRB5CCNAME should already be set. + * Now try to get an AFS token using aklog. + */ + if (k_hasafs()) { /* Do we have AFS? */ + + aklog_path = xstrdup(KPROGDIR); + + /* + * Make sure it exists before we try to run it + */ + if (stat(aklog_path, &st) == 0) { + debug("Running %s to get afs token.",aklog_path); + system(aklog_path); + } else { + debug("%s does not exist.",aklog_path); + } + + xfree(aklog_path); + } +#endif /* AFS_KRB5 */ + +#ifdef SESSION_HOOKS + if (options.session_hooks_allow && + options.session_hooks_startup_cmd) + { + execute_session_hook(options.session_hooks_startup_cmd, + s->authctxt, + /* startup = */ 1, + options.session_hooks_shutdown_cmd != NULL); + } +#endif + /* Change current directory to the user's home directory. */ if (chdir(pw->pw_dir) < 0) { fprintf(stderr, "Could not chdir to home directory %s: %s\n", @@ -1593,7 +1811,7 @@ /* Execute the shell. */ argv[0] = argv0; argv[1] = NULL; - execve(shell, argv, env); + execve(shell, argv, environ); /* Executing the shell failed. */ perror(shell); @@ -1607,7 +1825,7 @@ argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; - execve(shell, argv, env); + execve(shell, argv, environ); perror(shell); exit(1); } @@ -2017,11 +2235,18 @@ */ if (s->chanid == -1) fatal("no channel for session %d", s->self); - channel_set_fds(s->chanid, - fdout, fdin, fderr, - fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1, - CHAN_SES_WINDOW_DEFAULT); + if(options.hpn_disabled) + channel_set_fds(s->chanid, + fdout, fdin, fderr, + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, + 1, + CHAN_SES_WINDOW_DEFAULT); + else + channel_set_fds(s->chanid, + fdout, fdin, fderr, + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, + 1, + options.hpn_buffer_size); } /* @@ -2365,7 +2590,8 @@ } if (x11_create_display_inet(options.x11_display_offset, options.x11_use_localhost, s->single_connection, - &s->display_number, &s->x11_chanids) == -1) { + &s->display_number, &s->x11_chanids, + options.hpn_disabled, options.hpn_buffer_size) == -1) { debug("x11_create_display_inet failed."); return 0; } diff -Naur --exclude=autom4te.cache openssh-4.3p2/ssh.c openssh-4.3p2-gssapi/ssh.c --- openssh-4.3p2/ssh.c 2005-12-30 23:33:37.000000000 -0600 +++ openssh-4.3p2-gssapi/ssh.c 2006-07-26 15:17:38.000000000 -0500 @@ -469,9 +469,11 @@ case 'N': no_shell_flag = 1; no_tty_flag = 1; + options.none_switch = 0; break; case 'T': no_tty_flag = 1; + options.none_switch = 0; break; case 'o': dummy = 1; @@ -495,6 +497,14 @@ case 'F': config = optarg; break; + case 'z': + /* make sure we can't turn on the none_switch */ + /* if they try to force a no tty flag on a tty session */ + if (!no_tty_flag) { + options.none_switch = 1; + } + break; + default: usage(); } @@ -587,6 +597,29 @@ fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { + /* + * Since the config file parsing code aborts if it sees + * options it doesn't recognize, allow users to put + * options specific to compile-time add-ons in alternate + * config files so their primary config file will + * interoperate SSH versions that don't support those + * options. + */ +#ifdef GSSAPI + snprintf(buf, sizeof buf, "%.100s/%.100s.gssapi", pw->pw_dir, + _PATH_SSH_USER_CONFFILE); + (void)read_config_file(buf, host, &options, 1); +#ifdef GSI + snprintf(buf, sizeof buf, "%.100s/%.100s.gsi", pw->pw_dir, + _PATH_SSH_USER_CONFFILE); + (void)read_config_file(buf, host, &options, 1); +#endif +#if defined(KRB5) + snprintf(buf, sizeof buf, "%.100s/%.100s.krb", pw->pw_dir, + _PATH_SSH_USER_CONFFILE); + (void)read_config_file(buf, host, &options, 1); +#endif +#endif snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); (void)read_config_file(buf, host, &options, 1); @@ -606,8 +639,11 @@ seed_rng(); - if (options.user == NULL) + if (options.user == NULL) { options.user = xstrdup(pw->pw_name); + options.implicit = 1; + } + else options.implicit = 0; if (options.hostname != NULL) host = options.hostname; @@ -793,7 +829,8 @@ options.local_forwards[i].listen_port, options.local_forwards[i].connect_host, options.local_forwards[i].connect_port, - options.gateway_ports); + options.gateway_ports, options.hpn_disabled, + options.hpn_buffer_size); } if (i > 0 && success == 0) error("Could not request local forwarding."); @@ -1075,9 +1112,14 @@ debug("Requesting tun."); if ((fd = tun_open(options.tun_local, options.tun_open)) >= 0) { - c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, - 0, "tun", 1); + if(options.hpn_disabled) + c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "tun", 1); + else + c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, + options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, + 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (options.tun_open == SSH_TUNMODE_POINTOPOINT) @@ -1127,9 +1169,13 @@ if (!isatty(err)) set_nonblock(err); - window = CHAN_SES_WINDOW_DEFAULT; + if(options.hpn_disabled) + window = CHAN_SES_WINDOW_DEFAULT; + else + window = options.hpn_buffer_size; packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { + window = 4*CHAN_SES_PACKET_DEFAULT; window >>= 1; packetmax >>= 1; } @@ -1137,7 +1183,10 @@ "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); - + if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { + c->dynamic_window = 1; + debug ("Enabled Dynamic Window Scaling\n"); + } debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); @@ -1317,12 +1366,23 @@ flags |= SSHMUX_FLAG_X11_FWD; if (options.forward_agent) flags |= SSHMUX_FLAG_AGENT_FWD; - + if (options.num_local_forwards > 0) + flags |= SSHMUX_FLAG_PORTFORWARD; buffer_init(&m); /* Send our command to server */ buffer_put_int(&m, mux_command); buffer_put_int(&m, flags); + if (options.num_local_forwards > 0) + { + if (options.local_forwards[0].listen_host == NULL) + buffer_put_string(&m,"LOCALHOST",11); + else + buffer_put_string(&m,options.local_forwards[0].listen_host,512); + buffer_put_int(&m,options.local_forwards[0].listen_port); + buffer_put_string(&m,options.local_forwards[0].connect_host,512); + buffer_put_int(&m,options.local_forwards[0].connect_port); + } if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) fatal("%s: msg_send", __func__); buffer_clear(&m); diff -Naur --exclude=autom4te.cache openssh-4.3p2/ssh_config.5 openssh-4.3p2-gssapi/ssh_config.5 --- openssh-4.3p2/ssh_config.5 2006-01-31 04:39:03.000000000 -0600 +++ openssh-4.3p2-gssapi/ssh_config.5 2006-07-26 15:17:38.000000000 -0500 @@ -57,6 +57,12 @@ user's configuration file .Pq Pa ~/.ssh/config .It +GSSAPI configuration file +.Pq Pa $HOME/.ssh/config.gssapi +.It +Kerberos configuration file +.Pq Pa $HOME/.ssh/config.krb +.It system-wide configuration file .Pq Pa /etc/ssh/ssh_config .El @@ -463,14 +469,30 @@ .Pa /etc/ssh/ssh_known_hosts . .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. +The default is +.Dq yes . +Note that this option applies to protocol version 2 only. +.It Cm GSSAPIKeyExchange +Specifies whether key exchange based on GSSAPI may be used. When using +GSSAPI key exchange the server need not have a host key. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. .It Cm GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. +.It Cm GSSAPITrustDns +Set to +.Dq yes to indicate that the DNS is trusted to securely canonicalize +the name of the host being connected to. If +.Dq no, the hostname entered on the +command line will be passed untouched to the GSSAPI library. +The default is +.Dq yes . +This option only applies to protocol version 2 connections using GSSAPI +key exchange. .It Cm HashKnownHosts Indicates that .Nm ssh @@ -657,7 +679,7 @@ over another method (e.g.\& .Cm password ) The default for this option is: -.Dq hostbased,publickey,keyboard-interactive,password . +.Dq publickey,gssapi-keyex,external-keyx,gssapi-with-mic,gssapi,password,keyboard-interactive . .It Cm Protocol Specifies the protocol versions .Nm ssh diff -Naur --exclude=autom4te.cache openssh-4.3p2/sshconnect2.c openssh-4.3p2-gssapi/sshconnect2.c --- openssh-4.3p2/sshconnect2.c 2005-11-04 22:07:33.000000000 -0600 +++ openssh-4.3p2-gssapi/sshconnect2.c 2006-07-26 15:17:38.000000000 -0500 @@ -58,6 +58,12 @@ extern char *client_version_string; extern char *server_version_string; extern Options options; +extern Kex *xxx_kex; + +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ +/* if it is set then prevent the switch to the null cipher */ + +extern int tty_flag; /* * SSH2 key exchange @@ -84,9 +90,36 @@ { Kex *kex; +#ifdef GSSAPI + char *orig = NULL, *gss = NULL; + int len; + char *gss_host = NULL; +#endif + xxx_host = host; xxx_hostaddr = hostaddr; +#ifdef GSSAPI + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this client to + * the key exchange algorithm proposal */ + orig = myproposal[PROPOSAL_KEX_ALGS]; + if (options.gss_trust_dns) + gss_host = (char *)get_canonical_hostname(1); + else + gss_host = host; + + gss = ssh_gssapi_client_mechanisms(gss_host); + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); + len = strlen(orig) + strlen(gss) + 2; + myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len); + snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", gss, + orig); + } + } +#endif + if (options.ciphers == (char *)-1) { logit("No valid ciphers for protocol version 2 given, using defaults."); options.ciphers = NULL; @@ -94,7 +127,8 @@ if (options.ciphers != NULL) { myproposal[PROPOSAL_ENC_ALGS_CTOS] = myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); myproposal[PROPOSAL_ENC_ALGS_STOC] = @@ -114,6 +148,18 @@ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.hostkeyalgorithms; +#ifdef GSSAPI + /* If we've got GSSAPI algorithms, then we also support the + * 'null' hostkey, as a last resort */ + if (options.gss_keyex && gss) { + orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; + len = strlen(orig) + sizeof(",null"); + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len); + snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, + "%s,null", orig); + } +#endif + if (options.rekey_limit) packet_set_rekey_limit(options.rekey_limit); @@ -122,10 +168,20 @@ kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; +#ifdef GSSAPI + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; +#endif kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; +#ifdef GSSAPI + kex->gss_deleg_creds = options.gss_deleg_creds; + kex->gss_trust_dns = options.gss_trust_dns; + kex->gss_host = gss_host; +#endif + xxx_kex = kex; dispatch_run(DISPATCH_BLOCK, &kex->done, kex); @@ -202,12 +258,16 @@ int userauth_kerberos(Authctxt *); #ifdef GSSAPI +int userauth_external(Authctxt *authctxt); int userauth_gssapi(Authctxt *authctxt); +int userauth_gssapi_with_mic(Authctxt *authctxt); +int userauth_gssapi_without_mic(Authctxt *authctxt); void input_gssapi_response(int type, u_int32_t, void *); void input_gssapi_token(int type, u_int32_t, void *); void input_gssapi_hash(int type, u_int32_t, void *); void input_gssapi_error(int, u_int32_t, void *); void input_gssapi_errtok(int, u_int32_t, void *); +int userauth_gsskeyex(Authctxt *authctxt); #endif void userauth(Authctxt *, char *); @@ -223,10 +283,22 @@ Authmethod authmethods[] = { #ifdef GSSAPI + {"gssapi-keyex", + userauth_gsskeyex, + &options.gss_authentication, + NULL}, + {"external-keyx", + userauth_external, + &options.gss_authentication, + NULL}, {"gssapi-with-mic", userauth_gssapi, &options.gss_authentication, NULL}, + {"gssapi", + userauth_gssapi, + &options.gss_authentication, + NULL}, #endif {"hostbased", userauth_hostbased, @@ -309,7 +381,15 @@ pubkey_cleanup(&authctxt); dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); - + if ((options.none_switch == 1) && (options.none_enabled == 1) && !tty_flag) /* no null on tty sessions */ + { + debug("Requesting none rekeying..."); + myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; + myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; + kex_prop2buf(&xxx_kex->my,myproposal); + packet_request_rekeying(); + fprintf(stderr, "WARNING: ENABLED NULL CIPHER\n"); + } debug("Authentication succeeded (%s).", authctxt.method->name); } @@ -485,6 +565,17 @@ static u_int mech = 0; OM_uint32 min; int ok = 0; + char *gss_host = NULL; + + if (!options.gss_authentication) { + verbose("GSSAPI authentication disabled."); + return 0; + } + + if (options.gss_trust_dns) + gss_host = (char *)get_canonical_hostname(1); + else + gss_host = (char *)authctxt->host; /* Try one GSSAPI method at a time, rather than sending them all at * once. */ @@ -501,8 +592,10 @@ /* My DER encoding requires length<128 */ if (gss_supported->elements[mech].length < 128 && + ssh_gssapi_check_mechanism(&gss_supported->elements[mech], + gss_host) && !GSS_ERROR(ssh_gssapi_import_name(gssctxt, - authctxt->host))) { + gss_host))) { ok = 1; /* Mechanism works */ } else { mech++; @@ -566,7 +659,8 @@ if (status == GSS_S_COMPLETE) { /* send either complete or MIC, depending on mechanism */ - if (!(flags & GSS_C_INTEG_FLAG)) { + if (strcmp(authctxt->method->name,"gssapi")==0 || + (!(flags & GSS_C_INTEG_FLAG))) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); packet_send(); } else { @@ -598,8 +692,8 @@ { Authctxt *authctxt = ctxt; Gssctxt *gssctxt; - int oidlen; - char *oidv; + unsigned int oidlen; + unsigned char *oidv; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); @@ -706,6 +800,106 @@ xfree(msg); xfree(lang); } + +#ifdef GSI +extern +const gss_OID_desc * const gss_mech_globus_gssapi_openssl; +#define is_gsi_oid(oid) \ + (oid->length == gss_mech_globus_gssapi_openssl->length && \ + (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \ + oid->length) == 0)) +#endif + +int +userauth_external(Authctxt *authctxt) +{ + static int attempt = 0; + + if (attempt++ >= 1) + return 0; + + /* The client MUST NOT try this method if initial key exchange + was not performed using a GSSAPI-based key exchange + method. */ + if (gss_kex_context == NULL) { + debug2("gsskex not performed, skipping external-keyx"); + return 0; + } + + debug2("userauth_external"); + packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI + if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { + packet_put_cstring(""); + } else { +#endif + packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_send(); + packet_write_wait(); + return 1; +} +int +userauth_gsskeyex(Authctxt *authctxt) +{ + Buffer b; + gss_buffer_desc gssbuf; + gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; + OM_uint32 ms; + + static int attempt = 0; + if (attempt++ >= 1) + return (0); + + if (gss_kex_context == NULL) { + debug("No valid Key exchange context"); + return (0); + } + +#ifdef GSI + if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { + ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex"); + } else { +#endif + ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, + "gssapi-keyex"); +#ifdef GSI + } +#endif + + gssbuf.value = buffer_ptr(&b); + gssbuf.length = buffer_len(&b); + + if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { + buffer_free(&b); + return (0); + } + + packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI + if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { + packet_put_cstring(""); + } else { +#endif + packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_put_string(mic.value, mic.length); + packet_send(); + + buffer_free(&b); + gss_release_buffer(&ms, &mic); + + return (1); +} + #endif /* GSSAPI */ int diff -Naur --exclude=autom4te.cache openssh-4.3p2/sshconnect.c openssh-4.3p2-gssapi/sshconnect.c --- openssh-4.3p2/sshconnect.c 2005-12-13 02:29:03.000000000 -0600 +++ openssh-4.3p2-gssapi/sshconnect.c 2006-07-26 15:17:38.000000000 -0500 @@ -144,6 +144,31 @@ } /* + * Set TCP receive buffer if requested. + * Note: tuning needs to happen after the socket is + * created but before the connection happens + * so winscale is negotiated properly -cjr + */ +static void +ssh_set_socket_recvbuf(int sock) +{ + void *buf = (void *)&options.tcp_rcv_buf; + int sz = sizeof(options.tcp_rcv_buf); + int socksize; + int socksizelen = sizeof(int); + + debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); + debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); + } + else + error("Couldn't set socket receive buffer to %d: %.100s", + options.tcp_rcv_buf, strerror(errno)); +} + + +/* * Creates a (possibly privileged) socket for use as the ssh connection. */ static int @@ -166,13 +191,19 @@ strerror(errno)); else debug("Allocated local port %d.", p); + + if (options.tcp_rcv_buf > 0) + ssh_set_socket_recvbuf(sock); return sock; } sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) error("socket: %.100s", strerror(errno)); - - /* Bind the socket to an alternative local IP address */ + + if (options.tcp_rcv_buf > 0) + ssh_set_socket_recvbuf(sock); + + /* Bind the socket to an alternative local IP address */ if (options.bind_address == NULL) return sock; @@ -479,7 +510,7 @@ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, compat20 ? PROTOCOL_MINOR_2 : minor1, - SSH_VERSION); + SSH_RELEASE); if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) fatal("write: %.100s", strerror(errno)); client_version_string = xstrdup(buf); diff -Naur --exclude=autom4te.cache openssh-4.3p2/sshd.c openssh-4.3p2-gssapi/sshd.c --- openssh-4.3p2/sshd.c 2005-12-23 21:59:12.000000000 -0600 +++ openssh-4.3p2-gssapi/sshd.c 2006-07-26 15:17:38.000000000 -0500 @@ -86,6 +86,10 @@ #include "monitor_wrap.h" #include "monitor_fdpass.h" +#ifdef USE_SECURITY_SESSION_API +#include +#endif + #ifdef LIBWRAP #include #include @@ -377,7 +381,7 @@ major = PROTOCOL_MAJOR_1; minor = PROTOCOL_MINOR_1; } - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_RELEASE); server_version_string = xstrdup(buf); /* Send our protocol version identification. */ @@ -1123,10 +1127,13 @@ logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; } +#ifndef GSSAPI + /* The GSSAPI key exchange can run without a host key */ if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { logit("Disabling protocol version 2. Could not load host key"); options.protocol &= ~SSH_PROTO_2; } +#endif if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { logit("sshd: no hostkeys available -- exiting."); exit(1); @@ -1674,6 +1681,60 @@ /* Log the connection. */ verbose("Connection from %.500s port %d", remote_ip, remote_port); +#ifdef USE_SECURITY_SESSION_API + /* + * Create a new security session for use by the new user login if + * the current session is the root session or we are not launched + * by inetd (eg: debugging mode or server mode). We do not + * necessarily need to create a session if we are launched from + * inetd because Panther xinetd will create a session for us. + * + * The only case where this logic will fail is if there is an + * inetd running in a non-root session which is not creating + * new sessions for us. Then all the users will end up in the + * same session (bad). + * + * When the client exits, the session will be destroyed for us + * automatically. + * + * We must create the session before any credentials are stored + * (including AFS pags, which happens a few lines below). + */ + { + OSStatus err = 0; + SecuritySessionId sid = 0; + SessionAttributeBits sattrs = 0; + + err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); + if (err) + error("SessionGetInfo() failed with error %.8X", + (unsigned) err); + else + debug("Current Session ID is %.8X / Session Attributes are %.8X", + (unsigned) sid, (unsigned) sattrs); + + if (inetd_flag && !(sattrs & sessionIsRoot)) + debug("Running in inetd mode in a non-root session... " + "assuming inetd created the session for us."); + else { + debug("Creating new security session..."); + err = SessionCreate(0, sessionHasTTY | sessionIsRemote); + if (err) + error("SessionCreate() failed with error %.8X", + (unsigned) err); + + err = SessionGetInfo(callerSecuritySession, &sid, + &sattrs); + if (err) + error("SessionGetInfo() failed with error %.8X", + (unsigned) err); + else + debug("New Session ID is %.8X / Session Attributes are %.8X", + (unsigned) sid, (unsigned) sattrs); + } + } +#endif + /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is @@ -1687,6 +1748,13 @@ alarm(options.login_grace_time); sshd_exchange_identification(sock_in, sock_out); +#if defined(AFS_KRB5) + /* If machine has AFS, set process authentication group. */ + if (k_hasafs()) { + k_setpag(); + k_unlog(); + } +#endif /* AFS || AFS_KRB5 */ packet_set_nonblocking(); @@ -2007,6 +2075,10 @@ if (options.ciphers != NULL) { myproposal[PROPOSAL_ENC_ALGS_CTOS] = myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; + } else if (options.none_enabled == 1) { + debug ("WARNING: None cipher enabled"); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE; } myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); @@ -2028,13 +2100,63 @@ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); /* start key exchange */ - kex = kex_setup(myproposal); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + +#ifdef GSSAPI + { + char *orig; + char *gss = NULL; + char *newstr = NULL; + orig = myproposal[PROPOSAL_KEX_ALGS]; + + /* + * If we don't have a host key, then there's no point advertising + * the other key exchange algorithms + */ + + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) + orig = NULL; + + if (options.gss_keyex) + gss = ssh_gssapi_server_mechanisms(); + else + gss = NULL; + + if (gss && orig) { + int len = strlen(orig) + strlen(gss) + 2; + newstr = xmalloc(len); + snprintf(newstr, len, "%s,%s", gss, orig); + } else if (gss) { + newstr = gss; + } else if (orig) { + newstr = orig; + } + /* + * If we've got GSSAPI mechanisms, then we've got the 'null' host + * key alg, but we can't tell people about it unless its the only + * host key algorithm we support + */ + if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; + + if (newstr) + myproposal[PROPOSAL_KEX_ALGS] = newstr; + else + fatal("No supported key exchange algorithms"); + } +#endif + + /* start key exchange */ + kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; +#ifdef GSSAPI + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; +#endif + kex->server = 1; + kex->client_version_string=client_version_string; + kex->server_version_string=server_version_string; kex->load_host_key=&get_hostkey_by_type; kex->host_key_index=&get_hostkey_index; diff -Naur --exclude=autom4te.cache openssh-4.3p2/sshd_config openssh-4.3p2-gssapi/sshd_config --- openssh-4.3p2/sshd_config 2005-12-13 02:29:03.000000000 -0600 +++ openssh-4.3p2-gssapi/sshd_config 2006-07-26 15:17:38.000000000 -0500 @@ -65,8 +65,13 @@ #KerberosTicketCleanup yes #KerberosGetAFSToken no +# Session hooks: if allowed, specify the commands to execute +#AllowSessionHooks yes +#SessionHookStartupCmd /bin/true +#SessionHookShutdownCmd /bin/true + # GSSAPI options -#GSSAPIAuthentication no +#GSSAPIAuthentication yes #GSSAPICleanupCredentials yes # Set this to 'yes' to enable PAM authentication, account processing, @@ -98,8 +103,22 @@ #MaxStartups 10 #PermitTunnel no +# override default of no subsystems +Subsystem sftp /usr/libexec/sftp-server + # no default banner path #Banner /some/path -# override default of no subsystems -Subsystem sftp /usr/libexec/sftp-server +# the following are HPN related configuration options +# tcp receive buffer polling. enable in autotuning kernels +#TcpRcvBufPoll no + +# allow the use of the none cipher +#NoneEnabled no + +# disable hpn performance boosts. +#HPNDisabled no + +# buffer size for hpn to non-hn connections +#HPNBufferSize 2048 + diff -Naur --exclude=autom4te.cache openssh-4.3p2/sshd_config.5 openssh-4.3p2-gssapi/sshd_config.5 --- openssh-4.3p2/sshd_config.5 2006-01-03 01:47:31.000000000 -0600 +++ openssh-4.3p2-gssapi/sshd_config.5 2006-07-26 15:17:38.000000000 -0500 @@ -275,7 +275,13 @@ .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is -.Dq no . +.Dq yes . +Note that this option applies to protocol version 2 only. +.It Cm GSSAPIKeyExchange +Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange +doesn't rely on ssh keys to verify host identity. +The default is +.Dq yes . Note that this option applies to protocol version 2 only. .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache @@ -283,6 +289,11 @@ The default is .Dq yes . Note that this option applies to protocol version 2 only. +.It Cm GSIAllowLimitedProxy +Specifies whether to accept limited proxy credentials for +authentication. +The default is +.Dq no . .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed diff -Naur --exclude=autom4te.cache openssh-4.3p2/ssh-gss.h openssh-4.3p2-gssapi/ssh-gss.h --- openssh-4.3p2/ssh-gss.h 2004-06-21 21:56:02.000000000 -0500 +++ openssh-4.3p2-gssapi/ssh-gss.h 2006-07-26 15:17:38.000000000 -0500 @@ -36,6 +36,7 @@ #include #endif +#ifndef MECHGLUE #ifdef KRB5 # ifndef HEIMDAL # ifdef HAVE_GSSAPI_GENERIC_H @@ -51,6 +52,7 @@ #endif /* GSS_C_NT_... */ #endif /* !HEIMDAL */ #endif /* KRB5 */ +#endif /* !MECHGLUE */ /* draft-ietf-secsh-gsskeyex-06 */ #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 @@ -62,6 +64,16 @@ #define SSH_GSS_OIDTYPE 0x06 +#define SSH2_MSG_KEXGSS_INIT 30 +#define SSH2_MSG_KEXGSS_CONTINUE 31 +#define SSH2_MSG_KEXGSS_COMPLETE 32 +#define SSH2_MSG_KEXGSS_HOSTKEY 33 +#define SSH2_MSG_KEXGSS_ERROR 34 +#define SSH2_MSG_KEXGSS_GROUPREQ 40 +#define SSH2_MSG_KEXGSS_GROUP 41 +#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" +#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" + typedef struct { char *filename; char *envvar; @@ -75,6 +87,7 @@ gss_cred_id_t creds; struct ssh_gssapi_mech_struct *mech; ssh_gssapi_ccache store; + gss_ctx_id_t context; } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { @@ -92,13 +105,14 @@ OM_uint32 minor; /* both */ gss_ctx_id_t context; /* both */ gss_name_t name; /* both */ - gss_OID oid; /* client */ + gss_OID oid; /* both */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ gss_cred_id_t client_creds; /* server */ } Gssctxt; extern ssh_gssapi_mech *supported_mechs[]; +extern Gssctxt *gss_kex_context; int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); @@ -121,12 +135,29 @@ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); -/* In the server */ +int ssh_gssapi_localname(char **name); + +typedef int ssh_gssapi_check_fn(gss_OID, void *); +char *ssh_gssapi_client_mechanisms(const char *host); +char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, void *); +int ssh_gssapi_check_mechanism(gss_OID, void *); +gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int *); + +int ssh_gssapi_server_check_mech(gss_OID, void *); int ssh_gssapi_userok(char *name); OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_do_child(char ***, u_int *); void ssh_gssapi_cleanup_creds(void); void ssh_gssapi_storecreds(void); +char * ssh_gssapi_server_mechanisms(void); +int ssh_gssapi_oid_table_ok(); + +#ifdef MECHGLUE +gss_cred_id_t __gss_get_mechanism_cred + (gss_cred_id_t, /* union_cred */ + gss_OID /* mech_type */ + ); +#endif #endif /* GSSAPI */ diff -Naur --exclude=autom4te.cache openssh-4.3p2/version.h openssh-4.3p2-gssapi/version.h --- openssh-4.3p2/version.h 2006-02-10 18:00:45.000000000 -0600 +++ openssh-4.3p2-gssapi/version.h 2006-07-26 15:17:38.000000000 -0500 @@ -1,6 +1,27 @@ /* $OpenBSD: version.h,v 1.46 2006/02/01 11:27:22 markus Exp $ */ +#ifdef GSI +#define GSI_VERSION " GSI" +#else +#define GSI_VERSION "" +#endif + +#ifdef KRB5 +#define KRB5_VERSION " KRB5" +#else +#define KRB5_VERSION "" +#endif + +#ifdef MECHGLUE +#define MGLUE_VERSION " MECHGLUE" +#else +#define MGLUE_VERSION "" +#endif + #define SSH_VERSION "OpenSSH_4.3" #define SSH_PORTABLE "p2" -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE +#define SSH_HPN "-hpn12" +#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN \ + " NCSA_GSSAPI_20060726" \ + GSI_VERSION KRB5_VERSION MGLUE_VERSION