static protocol_t * protocol_ssl_accept(protocol_t * p, void *options) { protocol_t *newp; struct sockaddr_in remote; socklen_t addrlen; int ret; ssl_private_t *ssl_p = (ssl_private_t *) p->_protocol_p; ssl_private_t *new_ssl_p; struct sockaddr name; char hostname[128]; flowop_options_t *flowop_options = (flowop_options_t *) options; BIO *sbio; newp = protocol_ssl_new(); new_ssl_p = (ssl_private_t *) newp->_protocol_p; addrlen = (socklen_t) sizeof (remote); uperf_debug("ssl - ssl obj waiting for accept\n"); newp->fd = accept(p->fd, (struct sockaddr *) &remote, &addrlen); if (newp->fd < 0) { uperf_log_msg(UPERF_LOG_ERROR, errno, "accept"); return (NULL); } if (getnameinfo((const struct sockaddr *) & remote, addrlen, hostname, sizeof (hostname), NULL, 0, 0) == 0) { uperf_debug("ssl - Connection from %s:%d\n", hostname, SOCK_PORT(remote)); strlcpy(newp->host, hostname, sizeof (newp->host)); newp->port = SOCK_PORT(remote); } if (flowop_options) { if ((load_engine(flowop_options->engine)) == -1) { uperf_info( "ssl - Engine %s does NOT exist! Using the default OpenSSL softtoken", flowop_options->engine); } } sbio = BIO_new_socket(newp->fd, BIO_NOCLOSE); if (!(new_ssl_p->ssl = SSL_new(ctx))) { uperf_log_msg(UPERF_LOG_ERROR, 0, "SSL_new error"); return (NULL); } SSL_set_bio(new_ssl_p->ssl, sbio, sbio); ret = SSL_accept(new_ssl_p->ssl); if (my_ssl_error(new_ssl_p->ssl, ret) == 0) { return (newp); } else { return (0); } }
static krb5_error_code recvauth(int f, krb5_context krb_context, unsigned int *valid_checksum, krb5_ticket **ticket, int *auth_type, krb5_principal *client, int encr_flag, krb5_keytab keytab) { krb5_error_code status = 0; krb5_auth_context auth_context = NULL; krb5_rcache rcache; krb5_authenticator *authenticator; krb5_data inbuf; krb5_data auth_version; *valid_checksum = 0; if ((status = krb5_auth_con_init(krb_context, &auth_context))) return (status); /* Only need remote address for rd_cred() to verify client */ if ((status = krb5_auth_con_genaddrs(krb_context, auth_context, f, KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) return (status); status = krb5_auth_con_getrcache(krb_context, auth_context, &rcache); if (status) return (status); if (!rcache) { krb5_principal server; status = krb5_sname_to_principal(krb_context, 0, 0, KRB5_NT_SRV_HST, &server); if (status) return (status); status = krb5_get_server_rcache(krb_context, krb5_princ_component(krb_context, server, 0), &rcache); krb5_free_principal(krb_context, server); if (status) return (status); status = krb5_auth_con_setrcache(krb_context, auth_context, rcache); if (status) return (status); } if ((status = krb5_compat_recvauth(krb_context, &auth_context, &f, NULL, /* Specify daemon principal */ 0, /* no flags */ keytab, /* NULL to use v5srvtab */ ticket, /* return ticket */ auth_type, /* authentication system */ &auth_version))) { if (*auth_type == KRB5_RECVAUTH_V5) { /* * clean up before exiting */ getstr(f, rusername, sizeof (rusername), "remuser"); getstr(f, lusername, sizeof (lusername), "locuser"); getstr(f, term, sizeof (term), "Terminal type"); } return (status); } getstr(f, lusername, sizeof (lusername), "locuser"); getstr(f, term, sizeof (term), "Terminal type"); kcmd_protocol = KCMD_UNKNOWN_PROTOCOL; if (auth_version.length != 9 || auth_version.data == NULL) { syslog(LOG_ERR, "Bad application protocol version length in " "KRB5 exchange, exiting"); fatal(f, "Bad application version length, exiting."); } /* * Determine which Kerberos CMD protocol was used. */ if (strncmp(auth_version.data, "KCMDV0.1", 9) == 0) { kcmd_protocol = KCMD_OLD_PROTOCOL; } else if (strncmp(auth_version.data, "KCMDV0.2", 9) == 0) { kcmd_protocol = KCMD_NEW_PROTOCOL; } else { syslog(LOG_ERR, "Unrecognized KCMD protocol (%s), exiting", (char *)auth_version.data); fatal(f, "Unrecognized KCMD protocol, exiting"); } if ((*auth_type == KRB5_RECVAUTH_V5) && chksum_flag && kcmd_protocol == KCMD_OLD_PROTOCOL) { if ((status = krb5_auth_con_getauthenticator(krb_context, auth_context, &authenticator))) return (status); if (authenticator->checksum) { struct sockaddr_storage adr; int adr_length = sizeof (adr); int buflen; krb5_data input; krb5_keyblock key; char *chksumbuf; /* * Define the lenght of the chksum buffer. * chksum string = "[portnum]:termstr:username" * The extra 32 is to hold a integer string for * the portnumber. */ buflen = strlen(term) + strlen(lusername) + 32; chksumbuf = (char *)malloc(buflen); if (chksumbuf == 0) { krb5_free_authenticator(krb_context, authenticator); fatal(f, "Out of memory error"); } if (getsockname(f, (struct sockaddr *)&adr, &adr_length) != 0) { krb5_free_authenticator(krb_context, authenticator); fatal(f, "getsockname error"); } (void) snprintf(chksumbuf, buflen, "%u:%s%s", ntohs(SOCK_PORT(adr)), term, lusername); input.data = chksumbuf; input.length = strlen(chksumbuf); key.contents = (*ticket)->enc_part2->session->contents; key.length = (*ticket)->enc_part2->session->length; status = krb5_c_verify_checksum(krb_context, &key, 0, &input, authenticator->checksum, valid_checksum); if (status == 0 && *valid_checksum == 0) status = KRB5KRB_AP_ERR_BAD_INTEGRITY; if (chksumbuf) krb5_xfree(chksumbuf); if (status) { krb5_free_authenticator(krb_context, authenticator); return (status); } } krb5_free_authenticator(krb_context, authenticator); } if ((status = krb5_copy_principal(krb_context, (*ticket)->enc_part2->client, client))) return (status); /* Get the Unix username of the remote user */ getstr(f, rusername, sizeof (rusername), "remuser"); /* Get the Kerberos principal name string of the remote user */ if ((status = krb5_unparse_name(krb_context, *client, &krusername))) return (status); #ifdef DEBUG syslog(LOG_DEBUG | LOG_AUTH, "rlogind: got krb5 credentials for %s", (krusername != NULL ? krusername : "******")); #endif if (encr_flag) { status = krb5_auth_con_getremotesubkey(krb_context, auth_context, &session_key); if (status) { syslog(LOG_ERR, "Error getting KRB5 session " "subkey, exiting"); fatal(f, "Error getting KRB5 session subkey, exiting"); } /* * The "new" protocol requires that a subkey be sent. */ if (session_key == NULL && kcmd_protocol == KCMD_NEW_PROTOCOL) { syslog(LOG_ERR, "No KRB5 session subkey sent, exiting"); fatal(f, "No KRB5 session subkey sent, exiting"); } /* * The "old" protocol does not permit an authenticator subkey. * The key is taken from the ticket instead (see below). */ if (session_key != NULL && kcmd_protocol == KCMD_OLD_PROTOCOL) { syslog(LOG_ERR, "KRB5 session subkey not permitted " "with old KCMD protocol, exiting"); fatal(f, "KRB5 session subkey not permitted " "with old KCMD protocol, exiting"); } /* * If no key at this point, use the session key from * the ticket. */ if (session_key == NULL) { /* * Save the session key so we can configure the crypto * module later. */ status = krb5_copy_keyblock(krb_context, (*ticket)->enc_part2->session, &session_key); if (status) { syslog(LOG_ERR, "krb5_copy_keyblock failed"); fatal(f, "krb5_copy_keyblock failed"); } } /* * If session key still cannot be found, we must * exit because encryption is required here * when encr_flag (-x) is set. */ if (session_key == NULL) { syslog(LOG_ERR, "Could not find an encryption key," "exiting"); fatal(f, "Encryption required but key not found, " "exiting"); } } /* * Use krb5_read_message to read the principal stuff. */ if ((status = krb5_read_message(krb_context, (krb5_pointer)&f, &inbuf))) fatal(f, "Error reading krb5 message"); if (inbuf.length) { /* Forwarding being done, read creds */ krb5_creds **creds = NULL; if (status = krb5_rd_cred(krb_context, auth_context, &inbuf, &creds, NULL)) { if (rcache) (void) krb5_rc_close(krb_context, rcache); krb5_free_creds(krb_context, *creds); fatal(f, "Can't get forwarded credentials"); } /* Store the forwarded creds in the ccache */ if (status = store_forw_creds(krb_context, creds, *ticket, lusername, &ccache)) { if (rcache) (void) krb5_rc_close(krb_context, rcache); krb5_free_creds(krb_context, *creds); fatal(f, "Can't store forwarded credentials"); } krb5_free_creds(krb_context, *creds); } if (rcache) (void) krb5_rc_close(krb_context, rcache); return (status); }