X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fkrb5-security.c;h=c3075fa9bc2456d0aafd8afec557e4138f42d337;hb=HEAD;hp=dc70b318dcb49a00204c547a4b4bc4f91a435716;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/common-src/krb5-security.c b/common-src/krb5-security.c index dc70b31..c3075fa 100644 --- a/common-src/krb5-security.c +++ b/common-src/krb5-security.c @@ -37,11 +37,9 @@ #include "util.h" #include "event.h" #include "packet.h" -#include "queue.h" #include "security.h" #include "security-util.h" #include "stream.h" -#include "version.h" #include "sockaddr-util.h" #ifdef KRB5_HEIMDAL_INCLUDES @@ -116,15 +114,10 @@ */ #define GSS_TIMEOUT 30 -/* - * The largest buffer we can send/receive. - */ -#define AMANDA_MAX_TOK_SIZE (MAX_TAPE_BLOCK_BYTES * 4) - /* * This is the tcp stream buffer size */ -#define KRB5_STREAM_BUFSIZE (MAX_TAPE_BLOCK_BYTES * 2) +#define KRB5_STREAM_BUFSIZE (32768 * 2) /* * This is the max number of outgoing connections we can have at once. @@ -173,6 +166,9 @@ static int k5_encrypt(void *cookie, void *buf, ssize_t buflen, static int k5_decrypt(void *cookie, void *buf, ssize_t buflen, void **encbuf, ssize_t *encbuflen); +static ssize_t krb5_tcpm_recv_token(struct tcp_conn *rc, int fd, int *handle, + char **errmsg, char **buf, ssize_t *size, + int timeout); /* * This is our interface to the outside world. */ @@ -180,6 +176,7 @@ const security_driver_t krb5_security_driver = { "KRB5", krb5_connect, krb5_accept, + sec_get_authenticated_peer_name_hostname, sec_close, stream_sendpkt, stream_recvpkt, @@ -331,8 +328,8 @@ krb5_accept( void (*fn)(security_handle_t *, pkt_t *), void *datap) { - struct sockaddr_storage sin; - socklen_t len; + sockaddr_union sin; + socklen_t_equiv len; struct tcp_conn *rc; char hostname[NI_MAXHOST]; int result; @@ -511,7 +508,7 @@ gss_client( * Send back the response */ if (send_tok.length != 0 && tcpm_send_token(rc, rc->write, rs->handle, &errmsg, send_tok.value, send_tok.length) < 0) { - security_seterror(&rh->sech, rc->errmsg); + security_seterror(&rh->sech, "%s", rc->errmsg); gss_release_buffer(&min_stat, &send_tok); goto done; } @@ -523,7 +520,8 @@ gss_client( if (maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) break; - rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, + rvalue = krb5_tcpm_recv_token(rc, rc->read, &rc->handle, + &rc->errmsg, (void *)&recv_tok.value, (ssize_t *)&recv_tok.length, 60); if (rvalue <= 0) { @@ -556,7 +554,6 @@ gss_server( gss_name_t gss_name; gss_cred_id_t gss_creds; char *p, *realm, *msg; - uid_t euid; int rval = -1; int rvalue; char errbuf[256]; @@ -571,16 +568,9 @@ gss_server( * out of the default keytab. We also need to be root in * gss_accept_context() thanks to the replay cache code. */ - euid = geteuid(); - if (getuid() != 0) { - g_snprintf(errbuf, SIZEOF(errbuf), - _("real uid is %ld, needs to be 0 to read krb5 host key"), - (long)getuid()); - goto out; - } if (!set_root_privs(0)) { g_snprintf(errbuf, SIZEOF(errbuf), - _("can't seteuid to uid 0: %s"), strerror(errno)); + _("can't take root privileges to read krb5 host key: %s"), strerror(errno)); goto out; } @@ -619,7 +609,8 @@ gss_server( for (recv_tok.length = 0;;) { recv_tok.value = NULL; - rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, + rvalue = krb5_tcpm_recv_token(rc, rc->read, &rc->handle, + &rc->errmsg, /* (void *) is to avoid type-punning warning */ (char **)(void *)&recv_tok.value, (ssize_t *)&recv_tok.length, 60); @@ -1202,3 +1193,122 @@ common_exit: return(result); #endif /* AMANDA_PRINCIPAL */ } + +/* + * return -1 on error + * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed + * return 0 on EOF: *handle = handle && *size = 0 if stream closed + * return size : *handle = handle && *size = size for data read + */ + +static ssize_t +krb5_tcpm_recv_token( + struct tcp_conn *rc, + int fd, + int * handle, + char ** errmsg, + char ** buf, + ssize_t * size, + int timeout) +{ + unsigned int netint[2]; + + assert(SIZEOF(netint) == 8); + + switch (net_read(fd, &netint, SIZEOF(netint), timeout)) { + case -1: + if (errmsg) + *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno)); + auth_debug(1, _("krb5_tcpm_recv_token: A return(-1)\n")); + return (-1); + case 0: + *size = 0; + *handle = H_EOF; + *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); + auth_debug(1, _("krb5_tcpm_recv_token: A return(0)\n")); + return (0); + default: + break; + } + + *size = (ssize_t)ntohl(netint[0]); + *handle = (int)ntohl(netint[1]); + /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */ + if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) { + if (isprint((int)(*size ) & 0xFF) && + isprint((int)(*size >> 8 ) & 0xFF) && + isprint((int)(*size >> 16) & 0xFF) && + isprint((int)(*size >> 24) & 0xFF) && + isprint((*handle ) & 0xFF) && + isprint((*handle >> 8 ) & 0xFF) && + isprint((*handle >> 16) & 0xFF) && + isprint((*handle >> 24) & 0xFF)) { + char s[101]; + int i; + s[0] = ((int)(*size) >> 24) & 0xFF; + s[1] = ((int)(*size) >> 16) & 0xFF; + s[2] = ((int)(*size) >> 8) & 0xFF; + s[3] = ((int)(*size) ) & 0xFF; + s[4] = (*handle >> 24) & 0xFF; + s[5] = (*handle >> 16) & 0xFF; + s[6] = (*handle >> 8 ) & 0xFF; + s[7] = (*handle ) & 0xFF; + i = 8; s[i] = ' '; + while(i<100 && isprint((int)s[i]) && s[i] != '\n') { + switch(net_read(fd, &s[i], 1, 0)) { + case -1: s[i] = '\0'; break; + case 0: s[i] = '\0'; break; + default: + dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' '; + break; + } + } + s[i] = '\0'; + *errmsg = newvstrallocf(*errmsg, _("krb5_tcpm_recv_token: invalid size: %s"), s); + dbprintf(_("krb5_tcpm_recv_token: invalid size %s\n"), s); + } else { + *errmsg = newvstrallocf(*errmsg, _("krb5_tcpm_recv_token: invalid size")); + dbprintf(_("krb5_tcpm_recv_token: invalid size %zd\n"), *size); + } + *size = -1; + return -1; + } + amfree(*buf); + *buf = alloc((size_t)*size); + + if(*size == 0) { + auth_debug(1, _("krb5_tcpm_recv_token: read EOF from %d\n"), *handle); + *errmsg = newvstrallocf(*errmsg, _("EOF")); + return 0; + } + switch (net_read(fd, *buf, (size_t)*size, timeout)) { + case -1: + if (errmsg) + *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno)); + auth_debug(1, _("krb5_tcpm_recv_token: B return(-1)\n")); + return (-1); + case 0: + *size = 0; + *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); + auth_debug(1, _("krb5_tcpm_recv_token: B return(0)\n")); + return (0); + default: + break; + } + + auth_debug(1, _("krb5_tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle); + + if (*size > 0 && rc->driver->data_decrypt != NULL) { + void *decbuf; + ssize_t decsize; + rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize); + if (*buf != (char *)decbuf) { + amfree(*buf); + *buf = (char *)decbuf; + } + *size = decsize; + } + + return((*size)); +} +