KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL krb5_storage_from_socket(krb5_socket_t sock_in) { krb5_storage *sp; int saved_errno; krb5_socket_t sock; #ifdef _WIN32 WSAPROTOCOL_INFO info; if (WSADuplicateSocket(sock_in, GetCurrentProcessId(), &info) == 0) { sock = WSASocket( FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &info, 0, 0); } #else sock = dup(sock_in); #endif if (sock == rk_INVALID_SOCKET) return NULL; errno = ENOMEM; sp = malloc(sizeof(krb5_storage)); if (sp == NULL) { saved_errno = errno; rk_closesocket(sock); errno = saved_errno; return NULL; } errno = ENOMEM; sp->data = malloc(sizeof(socket_storage)); if (sp->data == NULL) { saved_errno = errno; rk_closesocket(sock); free(sp); errno = saved_errno; return NULL; } sp->flags = 0; sp->eof_code = HEIM_ERR_EOF; SOCK(sp) = sock; sp->fetch = socket_fetch; sp->store = socket_store; sp->seek = socket_seek; sp->trunc = socket_trunc; sp->fsync = socket_sync; sp->free = socket_free; sp->max_alloc = UINT_MAX/8; return sp; }
static void accept_it (rk_socket_t s, rk_socket_t *ret_socket) { rk_socket_t as; as = accept(s, NULL, NULL); if(rk_IS_BAD_SOCKET(as)) err (1, "accept"); if (ret_socket) { *ret_socket = as; } else { int fd = socket_to_fd(as, 0); /* We would use _O_RDONLY for the socket_to_fd() call for STDIN, but there are instances where we assume that STDIN is a r/w socket. */ dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); rk_closesocket(as); } }
/** * forcibly disconnect a sync client handle. * * @param[in] state pointer to sync client handle * * @retval operation status * @retval 0 success */ int SYNC_disconnect(SYNC_client_state * state) { rk_closesocket(state->fd); state->fd = OSI_NULLSOCKET; return 0; }
static int spawn_child(krb5_context contextp, int *socks, unsigned int num_socks, int this_sock) { int e; size_t i; struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; socklen_t sa_size = sizeof(__ss); krb5_socket_t s; pid_t pid; krb5_address addr; char buf[128]; size_t buf_len; s = accept(socks[this_sock], sa, &sa_size); if(rk_IS_BAD_SOCKET(s)) { krb5_warn(contextp, rk_SOCK_ERRNO, "accept"); return 1; } e = krb5_sockaddr2address(contextp, sa, &addr); if(e) krb5_warn(contextp, e, "krb5_sockaddr2address"); else { e = krb5_print_address (&addr, buf, sizeof(buf), &buf_len); if(e) krb5_warn(contextp, e, "krb5_print_address"); else krb5_warnx(contextp, "connection from %s", buf); krb5_free_address(contextp, &addr); } pid = fork(); if(pid == 0) { for(i = 0; i < num_socks; i++) rk_closesocket(socks[i]); dup2(s, STDIN_FILENO); dup2(s, STDOUT_FILENO); if(s != STDIN_FILENO && s != STDOUT_FILENO) rk_closesocket(s); return 0; } else { rk_closesocket(s); } return 1; }
static void socket_free(krb5_storage * sp) { int save_errno = errno; if (rk_IS_SOCKET_ERROR(rk_closesocket(SOCK(sp)))) errno = rk_SOCK_ERRNO; else errno = save_errno; }
static void slave_dead(krb5_context context, slave *s) { krb5_warnx(context, "slave %s dead", s->name); if (!rk_IS_BAD_SOCKET(s->fd)) { rk_closesocket (s->fd); s->fd = rk_INVALID_SOCKET; } s->flags |= SLAVE_F_DEAD; slave_seen(s); }
static int HandleOP(SetLoggingSocket) { int32_t portnum; krb5_socket_t sock; int ret; ret32(c, portnum); logmessage(c, __FILE__, __LINE__, 0, "logging port on peer is: %d", (int)portnum); socket_set_port((struct sockaddr *)(&c->sa), htons(portnum)); sock = socket(((struct sockaddr *)&c->sa)->sa_family, SOCK_STREAM, 0); if (sock == rk_INVALID_SOCKET) return 0; ret = connect(sock, (struct sockaddr *)&c->sa, c->salen); if (ret < 0) { logmessage(c, __FILE__, __LINE__, 0, "failed connect to log port: %s", strerror(errno)); rk_closesocket(sock); return 0; } if (c->logging) krb5_storage_free(c->logging); c->logging = krb5_storage_from_socket(sock); rk_closesocket(sock); krb5_store_int32(c->logging, eLogSetMoniker); store_string(c->logging, c->moniker); logmessage(c, __FILE__, __LINE__, 0, "logging turned on"); return 0; }
static void remove_slave (krb5_context context, slave *s, slave **root) { slave **p; if (!rk_IS_BAD_SOCKET(s->fd)) rk_closesocket (s->fd); if (s->name) free (s->name); if (s->ac) krb5_auth_con_free (context, s->ac); for (p = root; *p; p = &(*p)->next) if (*p == s) { *p = s->next; break; } free (s); }
static struct client * create_client(krb5_socket_t sock, int port, const char *moniker) { struct client *c; int ret; c = ecalloc(1, sizeof(*c)); if (moniker) { c->moniker = estrdup(moniker); } else { char hostname[MAXHOSTNAMELEN]; gethostname(hostname, sizeof(hostname)); ret = asprintf(&c->moniker, "gssmask: %s:%d", hostname, port); if (ret == -1) c->moniker = NULL; } if (!c->moniker) errx(1, "out of memory"); { c->salen = sizeof(c->sa); getpeername(sock, (struct sockaddr *)&c->sa, &c->salen); getnameinfo((struct sockaddr *)&c->sa, c->salen, c->servername, sizeof(c->servername), NULL, 0, NI_NUMERICHOST); } c->sock = krb5_storage_from_socket(sock); if (c->sock == NULL) errx(1, "krb5_storage_from_socket"); rk_closesocket(sock); return c; }
void start_server(krb5_context context, const char *port_str) { int e; struct kadm_port *p; krb5_socket_t *socks = NULL, *tmp; unsigned int num_socks = 0; int i; if (port_str == NULL) port_str = "+"; parse_ports(context, port_str); for(p = kadm_ports; p; p = p->next) { struct addrinfo hints, *ai, *ap; char portstr[32]; memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; e = getaddrinfo(NULL, p->port, &hints, &ai); if(e) { snprintf(portstr, sizeof(portstr), "%u", p->def_port); e = getaddrinfo(NULL, portstr, &hints, &ai); } if(e) { krb5_warn(context, krb5_eai_to_heim_errno(e, errno), "%s", portstr); continue; } i = 0; for(ap = ai; ap; ap = ap->ai_next) i++; tmp = realloc(socks, (num_socks + i) * sizeof(*socks)); if(tmp == NULL) { krb5_warnx(context, "failed to reallocate %lu bytes", (unsigned long)(num_socks + i) * sizeof(*socks)); continue; } socks = tmp; for(ap = ai; ap; ap = ap->ai_next) { krb5_socket_t s = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); if(rk_IS_BAD_SOCKET(s)) { krb5_warn(context, rk_SOCK_ERRNO, "socket"); continue; } socket_set_reuseaddr(s, 1); socket_set_ipv6only(s, 1); if (rk_IS_SOCKET_ERROR(bind (s, ap->ai_addr, ap->ai_addrlen))) { krb5_warn(context, rk_SOCK_ERRNO, "bind"); rk_closesocket(s); continue; } if (rk_IS_SOCKET_ERROR(listen (s, SOMAXCONN))) { krb5_warn(context, rk_SOCK_ERRNO, "listen"); rk_closesocket(s); continue; } socks[num_socks++] = s; } freeaddrinfo (ai); } if(num_socks == 0) krb5_errx(context, 1, "no sockets to listen to - exiting"); wait_for_connection(context, socks, num_socks); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_auth_context ac = NULL; krb5_principal c1, c2; krb5_authenticator authent; krb5_keytab keytab; krb5_socket_t sock = rk_INVALID_SOCKET; HDB *db = NULL; int optidx = 0; char *tmp_db; krb5_log_facility *fac; int nprincs; setprogname(argv[0]); ret = krb5_init_context(&context); if(ret) exit(1); ret = krb5_openlog(context, "hpropd", &fac); if(ret) errx(1, "krb5_openlog"); krb5_set_warn_dest(context, fac); if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if(local_realm != NULL) krb5_set_default_realm(context, local_realm); if(help_flag) usage(0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage(1); if (database == NULL) database = hdb_default_db(context); if(from_stdin) { sock = STDIN_FILENO; } else { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *)&ss; socklen_t sin_len = sizeof(ss); char addr_name[256]; krb5_ticket *ticket; char *server; sock = STDIN_FILENO; #ifdef SUPPORT_INETD if (inetd_flag == -1) { if (getpeername (sock, sa, &sin_len) < 0) { inetd_flag = 0; } else { inetd_flag = 1; } } #else inetd_flag = 0; #endif if (!inetd_flag) { mini_inetd (krb5_getportbyname (context, "hprop", "tcp", HPROP_PORT), &sock); } sin_len = sizeof(ss); if(getpeername(sock, sa, &sin_len) < 0) krb5_err(context, 1, errno, "getpeername"); if (inet_ntop(sa->sa_family, socket_get_address (sa), addr_name, sizeof(addr_name)) == NULL) strlcpy (addr_name, "unknown address", sizeof(addr_name)); krb5_log(context, fac, 0, "Connection from %s", addr_name); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); if (ktname != NULL) { ret = krb5_kt_resolve(context, ktname, &keytab); if (ret) krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname); } else { ret = krb5_kt_default (context, &keytab); if (ret) krb5_err (context, 1, ret, "krb5_kt_default"); } ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL, 0, keytab, &ticket); if(ret) krb5_err(context, 1, ret, "krb5_recvauth"); ret = krb5_unparse_name(context, ticket->server, &server); if (ret) krb5_err(context, 1, ret, "krb5_unparse_name"); if (strncmp(server, "hprop/", 5) != 0) krb5_errx(context, 1, "ticket not for hprop (%s)", server); free(server); krb5_free_ticket (context, ticket); ret = krb5_auth_con_getauthenticator(context, ac, &authent); if(ret) krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator"); ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL); if(ret) krb5_err(context, 1, ret, "krb5_make_principal"); _krb5_principalname2krb5_principal(context, &c2, authent->cname, authent->crealm); if(!krb5_principal_compare(context, c1, c2)) { char *s; ret = krb5_unparse_name(context, c2, &s); if (ret) s = unparseable_name; krb5_errx(context, 1, "Unauthorized connection from %s", s); } krb5_free_principal(context, c1); krb5_free_principal(context, c2); ret = krb5_kt_close(context, keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); } if(!print_dump) { asprintf(&tmp_db, "%s~", database); ret = hdb_create(context, &db, tmp_db); if(ret) krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db); ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600); if(ret) krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db); } nprincs = 0; while(1){ krb5_data data; hdb_entry_ex entry; if(from_stdin) { ret = krb5_read_message(context, &sock, &data); if(ret != 0 && ret != HEIM_ERR_EOF) krb5_err(context, 1, ret, "krb5_read_message"); } else { ret = krb5_read_priv_message(context, ac, &sock, &data); if(ret) krb5_err(context, 1, ret, "krb5_read_priv_message"); } if(ret == HEIM_ERR_EOF || data.length == 0) { if(!from_stdin) { data.data = NULL; data.length = 0; krb5_write_priv_message(context, ac, &sock, &data); } if(!print_dump) { ret = db->hdb_close(context, db); if(ret) krb5_err(context, 1, ret, "db_close"); ret = db->hdb_rename(context, db, database); if(ret) krb5_err(context, 1, ret, "db_rename"); } break; } memset(&entry, 0, sizeof(entry)); ret = hdb_value2entry(context, &data, &entry.entry); krb5_data_free(&data); if(ret) krb5_err(context, 1, ret, "hdb_value2entry"); if(print_dump) hdb_print_entry(context, db, &entry, stdout); else { ret = db->hdb_store(context, db, 0, &entry); if(ret == HDB_ERR_EXISTS) { char *s; ret = krb5_unparse_name(context, entry.entry.principal, &s); if (ret) s = strdup(unparseable_name); krb5_warnx(context, "Entry exists: %s", s); free(s); } else if(ret) krb5_err(context, 1, ret, "db_store"); else nprincs++; } hdb_free_entry(context, &entry); } if (!print_dump) krb5_log(context, fac, 0, "Received %d principals", nprincs); if (inetd_flag == 0) rk_closesocket(sock); exit(0); }
static kadm5_ret_t kadm_connect(kadm5_client_context *ctx) { kadm5_ret_t ret; krb5_principal server; krb5_ccache cc; rk_socket_t s = rk_INVALID_SOCKET; struct addrinfo *ai, *a; struct addrinfo hints; int error; char portstr[NI_MAXSERV]; char *hostname, *slash; char *service_name; krb5_context context = ctx->context; memset (&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf (portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port)); hostname = ctx->admin_server; slash = strchr (hostname, '/'); if (slash != NULL) hostname = slash + 1; error = getaddrinfo (hostname, portstr, &hints, &ai); if (error) { krb5_clear_error_message(context); return KADM5_BAD_SERVER_NAME; } for (a = ai; a != NULL; a = a->ai_next) { s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (s < 0) continue; if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { krb5_clear_error_message(context); krb5_warn (context, errno, "connect(%s)", hostname); rk_closesocket (s); continue; } break; } if (a == NULL) { freeaddrinfo (ai); krb5_clear_error_message(context); krb5_warnx (context, "failed to contact %s", hostname); return KADM5_FAILURE; } ret = _kadm5_c_get_cred_cache(context, ctx->client_name, ctx->service_name, NULL, ctx->prompter, ctx->keytab, ctx->ccache, &cc); if(ret) { freeaddrinfo (ai); rk_closesocket(s); return ret; } if (ctx->realm) asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm); else asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE); if (service_name == NULL) { freeaddrinfo (ai); rk_closesocket(s); krb5_clear_error_message(context); return ENOMEM; } ret = krb5_parse_name(context, service_name, &server); free(service_name); if(ret) { freeaddrinfo (ai); if(ctx->ccache == NULL) krb5_cc_close(context, cc); rk_closesocket(s); return ret; } ctx->ac = NULL; ret = krb5_sendauth(context, &ctx->ac, &s, KADMIN_APPL_VERSION, NULL, server, AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, cc, NULL, NULL, NULL); if(ret == 0) { krb5_data params; kadm5_config_params p; memset(&p, 0, sizeof(p)); if(ctx->realm) { p.mask |= KADM5_CONFIG_REALM; p.realm = ctx->realm; } ret = _kadm5_marshal_params(context, &p, ¶ms); ret = krb5_write_priv_message(context, ctx->ac, &s, ¶ms); krb5_data_free(¶ms); if(ret) { freeaddrinfo (ai); rk_closesocket(s); if(ctx->ccache == NULL) krb5_cc_close(context, cc); return ret; } } else if(ret == KRB5_SENDAUTH_BADAPPLVERS) { rk_closesocket(s); s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (s < 0) { freeaddrinfo (ai); krb5_clear_error_message(context); return errno; } if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { rk_closesocket (s); freeaddrinfo (ai); krb5_clear_error_message(context); return errno; } ret = krb5_sendauth(context, &ctx->ac, &s, KADMIN_OLD_APPL_VERSION, NULL, server, AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, cc, NULL, NULL, NULL); } freeaddrinfo (ai); if(ret) { rk_closesocket(s); return ret; } krb5_free_principal(context, server); if(ctx->ccache == NULL) krb5_cc_close(context, cc); ctx->sock = s; return 0; }
/****************************************************************************** * openlog * * Open connection to system logger. */ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL openlog( char* ident, int option, int facility ) { BOOL failed = FALSE; SOCKADDR_IN sa_local; DWORD n; int size; if ( !initialized ) return; EnterCriticalSection(&cs_syslog); if( syslog_opened ) goto done; failed = TRUE; syslog_facility = facility? facility : LOG_USER; if( option & LOG_PID ) sprintf_s( syslog_procid_str, sizeof(syslog_procid_str), "[%lu]", GetCurrentProcessId() ); else syslog_procid_str[0] = '\0'; /* FIXME: handle other options */ n = sizeof(local_hostname); if( !GetComputerName( local_hostname, &n ) ) goto done; syslog_socket = INVALID_SOCKET; init_logger_addr(); for( n = 0;; n++ ) { syslog_socket = socket( AF_INET, SOCK_DGRAM, 0 ); if( INVALID_SOCKET == syslog_socket ) goto done; memset( &sa_local, 0, sizeof(SOCKADDR_IN) ); sa_local.sin_family = AF_INET; if( bind( syslog_socket, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 ) break; rk_closesocket( syslog_socket ); syslog_socket = INVALID_SOCKET; if( n == 100 ) goto done; Sleep(0); } /* get size of datagramm */ size = sizeof(datagramm_size); if( getsockopt( syslog_socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) ) goto done; if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 ) goto done; if( datagramm_size > SYSLOG_DGRAM_SIZE ) datagramm_size = SYSLOG_DGRAM_SIZE; if (ident) strcpy_s(syslog_ident, sizeof(syslog_ident), ident); syslog_facility = (facility ? facility : LOG_USER); failed = FALSE; done: if( failed ) { if( syslog_socket != INVALID_SOCKET ) rk_closesocket( syslog_socket ); } syslog_opened = !failed; LeaveCriticalSection(&cs_syslog); }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendto (krb5_context context, const krb5_data *send_data, krb5_krbhst_handle handle, krb5_data *receive) { krb5_error_code ret; krb5_socket_t fd; size_t i; krb5_data_zero(receive); for (i = 0; i < context->max_retries; ++i) { krb5_krbhst_info *hi; while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; _krb5_debug(context, 2, "trying to communicate with host %s in realm %s", hi->hostname, _krb5_krbhst_get_realm(handle)); if (context->send_to_kdc) { struct send_to_kdc *s = context->send_to_kdc; ret = (*s->func)(context, s->data, hi, context->kdc_timeout, send_data, receive); if (ret == 0 && receive->length != 0) goto out; continue; } ret = send_via_plugin(context, hi, context->kdc_timeout, send_data, receive); if (ret == 0 && receive->length != 0) goto out; else if (ret != KRB5_PLUGIN_NO_HANDLE) continue; if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { if (send_via_proxy (context, hi, send_data, receive) == 0) { ret = 0; goto out; } continue; } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); if (ret) continue; for (a = ai; a != NULL; a = a->ai_next) { fd = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (rk_IS_BAD_SOCKET(fd)) continue; rk_cloexec(fd); if (timed_connect (fd, a, context->kdc_timeout) < 0) { rk_closesocket (fd); continue; } switch (hi->proto) { case KRB5_KRBHST_HTTP : ret = send_and_recv_http(fd, context->kdc_timeout, "", send_data, receive); break; case KRB5_KRBHST_TCP : ret = send_and_recv_tcp (fd, context->kdc_timeout, send_data, receive); break; case KRB5_KRBHST_UDP : ret = send_and_recv_udp (fd, context->kdc_timeout, send_data, receive); break; } rk_closesocket (fd); if(ret == 0 && receive->length != 0) goto out; } } krb5_krbhst_reset(context, handle); } krb5_clear_error_message (context); ret = KRB5_KDC_UNREACH; out: _krb5_debug(context, 2, "result of trying to talk to realm %s = %d", _krb5_krbhst_get_realm(handle), ret); return ret; }
static int send_via_proxy (krb5_context context, const krb5_krbhst_info *hi, const krb5_data *send_data, krb5_data *receive) { char *proxy2 = strdup(context->http_proxy); char *proxy = proxy2; char *prefix = NULL; char *colon; struct addrinfo hints; struct addrinfo *ai, *a; int ret; krb5_socket_t s = rk_INVALID_SOCKET; char portstr[NI_MAXSERV]; if (proxy == NULL) return ENOMEM; if (strncmp (proxy, "http://", 7) == 0) proxy += 7; colon = strchr(proxy, ':'); if(colon != NULL) *colon++ = '\0'; memset (&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf (portstr, sizeof(portstr), "%d", ntohs(init_port (colon, htons(80)))); ret = getaddrinfo (proxy, portstr, &hints, &ai); free (proxy2); if (ret) return krb5_eai_to_heim_errno(ret, errno); for (a = ai; a != NULL; a = a->ai_next) { s = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (s < 0) continue; rk_cloexec(s); if (timed_connect (s, a, context->kdc_timeout) < 0) { rk_closesocket (s); continue; } break; } if (a == NULL) { freeaddrinfo (ai); return 1; } freeaddrinfo (ai); ret = asprintf(&prefix, "http://%s/", hi->hostname); if(ret < 0 || prefix == NULL) { close(s); return 1; } ret = send_and_recv_http(s, context->kdc_timeout, prefix, send_data, receive); rk_closesocket (s); free(prefix); if(ret == 0 && receive->length != 0) return 0; return 1; }