X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fkrb5-security.c;h=c3075fa9bc2456d0aafd8afec557e4138f42d337;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=5b3d76a416afe55584d4e0c245fbc3caaf0c9350;hpb=d3b2175e084f88c8736ad7073eacbf4670147aec;p=debian%2Famanda diff --git a/common-src/krb5-security.c b/common-src/krb5-security.c index 5b3d76a..c3075fa 100644 --- a/common-src/krb5-security.c +++ b/common-src/krb5-security.c @@ -37,18 +37,15 @@ #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 #include "com_err.h" #endif -#ifdef KRB5_SECURITY - #define BROKEN_MEMORY_CCACHE #ifdef BROKEN_MEMORY_CCACHE @@ -76,23 +73,12 @@ #define KRB5_ENV_CCNAME "KRB5CCNAME" #endif -#define k5printf(x) auth_debug(1,x) - - /* * consider undefining when kdestroy() is fixed. The current version does * not work under krb5-1.2.4 in rh7.3, perhaps others. */ #define KDESTROY_VIA_UNLINK 1 -/* - * Define this if you want all network traffic encrypted. This will - * extract a serious performance hit. - * - * It would be nice if we could do this on a filesystem-by-filesystem basis. - */ -/*#define AMANDA_KRB5_ENCRYPT*/ - /* * Where the keytab lives, if defined. Otherwise it expects something in the * config file. @@ -128,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. @@ -161,8 +142,11 @@ static char myhostname[MAX_HOSTNAME_LENGTH+1]; /* * Interface functions */ -static void krb5_accept(const struct security_driver *, int, int, - void (*)(security_handle_t *, pkt_t *)); +static void krb5_accept(const struct security_driver *, + char *(*)(char *, void *), + int, int, + void (*)(security_handle_t *, pkt_t *), + void *); static void krb5_connect(const char *, char *(*)(char *, void *), void (*)(void *, security_handle_t *, security_status_t), void *, void *); @@ -177,13 +161,14 @@ static int gss_client(struct sec_handle *); static const char *gss_error(OM_uint32, OM_uint32); static char *krb5_checkuser(char *host, char *name, char *realm); -#ifdef AMANDA_KRB5_ENCRYPT static int k5_encrypt(void *cookie, void *buf, ssize_t buflen, void **encbuf, ssize_t *encbuflen); static int k5_decrypt(void *cookie, void *buf, ssize_t buflen, void **encbuf, ssize_t *encbuflen); -#endif +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. */ @@ -191,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, @@ -206,13 +192,8 @@ const security_driver_t krb5_security_driver = { tcpm_stream_read_sync, tcpm_stream_read_cancel, tcpm_close_connection, -#ifdef AMANDA_KRB5_ENCRYPT k5_encrypt, k5_decrypt, -#else - NULL, - NULL, -#endif }; static int newhandle = 1; @@ -239,16 +220,12 @@ krb5_connect( { struct sec_handle *rh; int result; - struct addrinfo hints; - struct addrinfo *res = NULL; + char *canonname; assert(fn != NULL); assert(hostname != NULL); - (void)conf_fn; /* Quiet unused parameter warning */ - (void)datap; /* Quiet unused parameter warning */ - k5printf(("%s: krb5: krb5_connect: %s\n", debug_prefix_time(NULL), - hostname)); + auth_debug(1, "krb5: krb5_connect: %s\n", hostname); krb5_init(); @@ -259,37 +236,27 @@ krb5_connect( rh->ev_timeout = NULL; rh->rc = NULL; -#ifdef WORKING_IPV6 - hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL; - hints.ai_family = AF_UNSPEC; -#else - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; -#endif - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - result = getaddrinfo(hostname, NULL, &hints, &res); -#ifdef WORKING_IPV6 - if (result != 0) { - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; - result = getaddrinfo(hostname, NULL, &hints, &res); - } -#endif + result = resolve_hostname(hostname, 0, NULL, &canonname); if(result != 0) { - dbprintf(("krb5_connect: getaddrinfo(%s): %s\n", hostname, gai_strerror(result))); - security_seterror(&rh->sech, "getaddrinfo(%s): %s\n", hostname, + dbprintf(_("resolve_hostname(%s): %s\n"), hostname, gai_strerror(result)); + security_seterror(&rh->sech, _("resolve_hostname(%s): %s\n"), hostname, gai_strerror(result)); (*fn)(arg, &rh->sech, S_ERROR); return; } + if (canonname == NULL) { + dbprintf(_("resolve_hostname(%s) did not return a canonical name\n"), hostname); + security_seterror(&rh->sech, + _("resolve_hostname(%s) did not return a canonical name\n"), hostname); + (*fn)(arg, &rh->sech, S_ERROR); + return; + } - rh->hostname = stralloc(res->ai_canonname); /* will be replaced */ + rh->hostname = canonname; /* will be replaced */ + canonname = NULL; /* steal reference */ rh->rs = tcpma_stream_client(rh, newhandle++); + rh->rc->conf_fn = conf_fn; + rh->rc->datap = datap; rh->rc->recv_security_ok = NULL; rh->rc->prefix_packet = NULL; @@ -340,24 +307,29 @@ krb5_connect( rh->ev_timeout = event_register(CONNECT_TIMEOUT, EV_TIME, sec_connect_timeout, rh); + amfree(canonname); return; error: + amfree(canonname); (*fn)(arg, &rh->sech, S_ERROR); } /* + * Setup to handle new incoming connections */ static void krb5_accept( const struct security_driver *driver, + char *(*conf_fn)(char *, void *), int in, int out, - void (*fn)(security_handle_t *, pkt_t *)) + 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; @@ -367,26 +339,32 @@ krb5_accept( len = sizeof(sin); if (getpeername(in, (struct sockaddr *)&sin, &len) < 0) { - dbprintf(("%s: getpeername returned: %s\n", debug_prefix_time(NULL), - strerror(errno))); + dbprintf(_("getpeername returned: %s\n"), + strerror(errno)); return; + } if ((result = getnameinfo((struct sockaddr *)&sin, len, hostname, NI_MAXHOST, NULL, 0, 0) != 0)) { - dbprintf(("%s: getnameinfo failed: %s\n", - debug_prefix_time(NULL), gai_strerror(result))); + dbprintf(_("getnameinfo failed: %s\n"), + gai_strerror(result)); return; } if (check_name_give_sockaddr(hostname, (struct sockaddr *)&sin, &errmsg) < 0) { + dbprintf(_("check_name_give_sockaddr(%s): %s\n"), + hostname, errmsg); amfree(errmsg); return; } + rc = sec_tcp_conn_get(hostname, 0); + rc->conf_fn = conf_fn; + rc->datap = datap; rc->recv_security_ok = NULL; rc->prefix_packet = NULL; - memcpy(&rc->peer, &sin, sizeof(rc->peer)); + copy_sockaddr(&rc->peer, &sin); rc->read = in; rc->write = out; rc->driver = driver; @@ -407,7 +385,6 @@ runkrb5( struct servent * sp; int server_socket; in_port_t my_port, port; - uid_t euid; struct tcp_conn * rc = rh->rc; const char *err; @@ -416,20 +393,20 @@ runkrb5( else port = sp->s_port; - euid = geteuid(); - if ((err = get_tgt(keytab_name, principal_name)) != NULL) { security_seterror(&rh->sech, "%s: could not get TGT: %s", rc->hostname, err); return -1; } + set_root_privs(1); server_socket = stream_client(rc->hostname, (in_port_t)(ntohs(port)), STREAM_BUFSIZE, STREAM_BUFSIZE, &my_port, 0); + set_root_privs(0); if(server_socket < 0) { security_seterror(&rh->sech, @@ -437,7 +414,6 @@ runkrb5( return -1; } - seteuid(euid); rc->read = rc->write = server_socket; @@ -445,11 +421,14 @@ runkrb5( return -1; } + return 0; } + /* + * Negotiate a krb5 gss context from the client end. */ static int @@ -467,14 +446,14 @@ gss_client( gss_name_t gss_name; char *errmsg = NULL; - k5printf(("gss_client\n")); + auth_debug(1, "gss_client\n"); send_tok.value = vstralloc("host/", rs->rc->hostname, NULL); send_tok.length = strlen(send_tok.value) + 1; maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID, &gss_name); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { - security_seterror(&rh->sech, "can't import name %s: %s", + security_seterror(&rh->sech, _("can't import name %s: %s"), (char *)send_tok.value, gss_error(maj_stat, min_stat)); amfree(send_tok.value); return (-1); @@ -482,7 +461,7 @@ gss_client( amfree(send_tok.value); rc->gss_context = GSS_C_NO_CONTEXT; maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid); - dbprintf(("gss_name %s\n", (char *)AA.value)); + dbprintf(_("gss_name %s\n"), (char *)AA.value); /* * Perform the context-establishement loop. @@ -520,7 +499,7 @@ gss_client( } if (maj_stat != (OM_uint32)GSS_S_COMPLETE && maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) { security_seterror(&rh->sech, - "error getting gss context: %s %s", + _("error getting gss context: %s %s"), gss_error(maj_stat, min_stat), (char *)send_tok.value); goto done; } @@ -529,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; } @@ -541,15 +520,16 @@ 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) { if (rvalue < 0) security_seterror(&rh->sech, - "recv error in gss loop: %s", rc->errmsg); + _("recv error in gss loop: %s"), rc->errmsg); else - security_seterror(&rh->sech, "EOF in gss loop"); + security_seterror(&rh->sech, _("EOF in gss loop")); goto done; } } @@ -574,13 +554,12 @@ 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]; char *errmsg = NULL; - k5printf(("gss_server\n")); + auth_debug(1, "gss_server\n"); assert(rc != NULL); @@ -589,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) { - snprintf(errbuf, SIZEOF(errbuf), - "real uid is %ld, needs to be 0 to read krb5 host key", - (long)getuid()); - goto out; - } - if (seteuid(0) < 0) { - snprintf(errbuf, SIZEOF(errbuf), - "can't seteuid to uid 0: %s", strerror(errno)); + if (!set_root_privs(0)) { + g_snprintf(errbuf, SIZEOF(errbuf), + _("can't take root privileges to read krb5 host key: %s"), strerror(errno)); goto out; } @@ -612,9 +584,9 @@ gss_server( maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID, &gss_name); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { - seteuid(euid); - snprintf(errbuf, SIZEOF(errbuf), - "can't import name %s: %s", (char *)send_tok.value, + set_root_privs(0); + g_snprintf(errbuf, SIZEOF(errbuf), + _("can't import name %s: %s"), (char *)send_tok.value, gss_error(maj_stat, min_stat)); amfree(send_tok.value); goto out; @@ -622,31 +594,33 @@ gss_server( amfree(send_tok.value); maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid); - dbprintf(("gss_name %s\n", (char *)AA.value)); + dbprintf(_("gss_name %s\n"), (char *)AA.value); maj_stat = gss_acquire_cred(&min_stat, gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &gss_creds, NULL, NULL); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { - snprintf(errbuf, SIZEOF(errbuf), - "can't acquire creds for host key host/%s: %s", myhostname, + g_snprintf(errbuf, SIZEOF(errbuf), + _("can't acquire creds for host key host/%s: %s"), myhostname, gss_error(maj_stat, min_stat)); gss_release_name(&min_stat, &gss_name); - seteuid(euid); + set_root_privs(0); goto out; } gss_release_name(&min_stat, &gss_name); for (recv_tok.length = 0;;) { recv_tok.value = NULL; - rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, - (char **)&recv_tok.value, + 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); if (rvalue <= 0) { if (rvalue < 0) { - snprintf(errbuf, SIZEOF(errbuf), - "recv error in gss loop: %s", rc->errmsg); + g_snprintf(errbuf, SIZEOF(errbuf), + _("recv error in gss loop: %s"), rc->errmsg); amfree(rc->errmsg); } else - snprintf(errbuf, SIZEOF(errbuf), "EOF in gss loop"); + g_snprintf(errbuf, SIZEOF(errbuf), _("EOF in gss loop")); goto out; } @@ -656,8 +630,8 @@ gss_server( if (maj_stat != (OM_uint32)GSS_S_COMPLETE && maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) { - snprintf(errbuf, SIZEOF(errbuf), - "error accepting context: %s", gss_error(maj_stat, min_stat)); + g_snprintf(errbuf, SIZEOF(errbuf), + _("error accepting context: %s"), gss_error(maj_stat, min_stat)); amfree(recv_tok.value); goto out; } @@ -683,8 +657,8 @@ gss_server( maj_stat = gss_display_name(&min_stat, gss_name, &send_tok, &doid); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { - snprintf(errbuf, SIZEOF(errbuf), - "can't display gss name: %s", gss_error(maj_stat, min_stat)); + g_snprintf(errbuf, SIZEOF(errbuf), + _("can't display gss name: %s"), gss_error(maj_stat, min_stat)); gss_release_name(&min_stat, &gss_name); goto out; } @@ -692,8 +666,8 @@ gss_server( /* get rid of the realm */ if ((p = strchr(send_tok.value, '@')) == NULL) { - snprintf(errbuf, SIZEOF(errbuf), - "malformed gss name: %s", (char *)send_tok.value); + g_snprintf(errbuf, SIZEOF(errbuf), + _("malformed gss name: %s"), (char *)send_tok.value); amfree(send_tok.value); goto out; } @@ -704,8 +678,8 @@ gss_server( * If the principal doesn't match, complain */ if ((msg = krb5_checkuser(rc->hostname, send_tok.value, realm)) != NULL) { - snprintf(errbuf, SIZEOF(errbuf), - "access not allowed from %s: %s", (char *)send_tok.value, msg); + g_snprintf(errbuf, SIZEOF(errbuf), + _("access not allowed from %s: %s"), (char *)send_tok.value, msg); amfree(send_tok.value); goto out; } @@ -713,13 +687,13 @@ gss_server( rval = 0; out: - seteuid(euid); + set_root_privs(0); if (rval != 0) { rc->errmsg = stralloc(errbuf); } else { rc->auth = 1; } - k5printf(("gss_server returning %d\n", rval)); + auth_debug(1, _("gss_server returning %d\n"), rval); return (rval); } @@ -752,7 +726,7 @@ krb5_init(void) { char *ccache; ccache = malloc(128); - snprintf(ccache, SIZEOF(ccache), + g_snprintf(ccache, SIZEOF(ccache), "KRB5_ENV_CCNAME=FILE:/tmp/amanda_ccache.%ld.%ld", (long)geteuid(), (long)getpid()); putenv(ccache); @@ -766,7 +740,7 @@ krb5_init(void) * In case it isn't fully qualified, do a DNS lookup. Ignore * any errors (this is best-effort). */ - if (try_resolving_hostname(myhostname, &myfqhostname) == 0 + if (resolve_hostname(myhostname, SOCK_STREAM, NULL, &myfqhostname) == 0 && myfqhostname != NULL) { strncpy(myhostname, myfqhostname, SIZEOF(myhostname)-1); myhostname[SIZEOF(myhostname)-1] = '\0'; @@ -789,7 +763,7 @@ cleanup(void) { #ifdef KDESTROY_VIA_UNLINK char ccache[64]; - snprintf(ccache, SIZEOF(ccache), "/tmp/amanda_ccache.%ld.%ld", + g_snprintf(ccache, SIZEOF(ccache), "/tmp/amanda_ccache.%ld.%ld", (long)geteuid(), (long)getpid()); unlink(ccache); #else @@ -825,20 +799,20 @@ get_tgt( error = NULL; } if ((ret = krb5_init_context(&context)) != 0) { - error = vstralloc("error initializing krb5 context: ", - error_message(ret), NULL); + error = vstrallocf(_("error initializing krb5 context: %s"), + error_message(ret)); return (error); } /*krb5_init_ets(context);*/ if(!keytab_name) { - error = vstralloc("error -- no krb5 keytab defined", NULL); + error = vstrallocf(_("error -- no krb5 keytab defined")); return(error); } if(!principal_name) { - error = vstralloc("error -- no krb5 principal defined", NULL); + error = vstrallocf(_("error -- no krb5 principal defined")); return(error); } @@ -846,8 +820,8 @@ get_tgt( * Resolve keytab file into a keytab object */ if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) { - error = vstralloc("error resolving keytab ", keytab_name, ": ", - error_message(ret), NULL); + error = vstrallocf(_("error resolving keytab %s: %s"), keytab_name, + error_message(ret)); return (error); } @@ -857,8 +831,8 @@ get_tgt( */ ret = krb5_parse_name(context, principal_name, &client); if (ret != 0) { - error = vstralloc("error parsing ", principal_name, ": ", - error_message(ret), NULL); + error = vstrallocf(_("error parsing %s: %s"), principal_name, + error_message(ret)); return (error); } @@ -880,15 +854,14 @@ get_tgt( 0); #endif if (ret != 0) { - error = vstralloc("error while building server name: ", - error_message(ret), NULL); + error = vstrallocf(_("error while building server name: %s"), + error_message(ret)); return (error); } ret = krb5_timeofday(context, &now); if (ret != 0) { - error = vstralloc("error getting time of day: ", error_message(ret), - NULL); + error = vstrallocf(_("error getting time of day: %s"), error_message(ret)); return (error); } @@ -906,24 +879,22 @@ get_tgt( keytab, 0, &creds, 0); if (ret != 0) { - error = vstralloc("error getting ticket for ", principal_name, - ": ", error_message(ret), NULL); + error = vstrallocf(_("error getting ticket for %s: %s"), + principal_name, error_message(ret)); goto cleanup2; } if ((ret = krb5_cc_default(context, &ccache)) != 0) { - error = vstralloc("error initializing ccache: ", error_message(ret), - NULL); + error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) { - error = vstralloc("error initializing ccache: ", error_message(ret), - NULL); + error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) { - error = vstralloc("error storing creds in ccache: ", - error_message(ret), NULL); + error = vstrallocf(_("error storing creds in ccache: %s"), + error_message(ret)); /* FALLTHROUGH */ } krb5_cc_close(context, ccache); @@ -988,7 +959,6 @@ gss_error( return ((const char *)msg.value); } -#ifdef AMANDA_KRB5_ENCRYPT static int k5_encrypt( void *cookie, @@ -1003,31 +973,36 @@ k5_encrypt( OM_uint32 maj_stat, min_stat; int conf_state; - k5printf(("krb5: k5_encrypt: enter %p\n", rc)); - - dectok.length = buflen; - dectok.value = buf; - - if (rc->auth == 1) { - assert(rc->gss_context != GSS_C_NO_CONTEXT); - maj_stat = gss_seal(&min_stat, rc->gss_context, 1, - GSS_C_QOP_DEFAULT, &dectok, &conf_state, &enctok); - if (maj_stat != (OM_uint32)GSS_S_COMPLETE || conf_state == 0) { - k5printf(("krb5 encrypt error to %s: %s\n", - rc->hostname, gss_error(maj_stat, min_stat))); - return (-1); + if (rc->conf_fn && rc->conf_fn("kencrypt", rc->datap)) { + auth_debug(1, _("krb5: k5_encrypt: enter %p\n"), rc); + + dectok.length = buflen; + dectok.value = buf; + + if (rc->auth == 1) { + assert(rc->gss_context != GSS_C_NO_CONTEXT); + maj_stat = gss_seal(&min_stat, rc->gss_context, 1, + GSS_C_QOP_DEFAULT, &dectok, &conf_state, + &enctok); + if (maj_stat != (OM_uint32)GSS_S_COMPLETE || conf_state == 0) { + auth_debug(1, _("krb5 encrypt error to %s: %s\n"), + rc->hostname, gss_error(maj_stat, min_stat)); + return (-1); + } + auth_debug(1, _("krb5: k5_encrypt: give %zu bytes\n"), + enctok.length); + *encbuf = enctok.value; + *encbuflen = enctok.length; + } else { + *encbuf = buf; + *encbuflen = buflen; } - k5printf(("krb5: k5_encrypt: give %zu bytes\n", enctok.length)); - *encbuf = enctok.value; - *encbuflen = enctok.length; - } else { - *encbuf = buf; - *encbuflen = buflen; + auth_debug(1, _("krb5: k5_encrypt: exit\n")); } - k5printf(("krb5: k5_encrypt: exit\n")); return (0); } + static int k5_decrypt( void *cookie, @@ -1042,33 +1017,37 @@ k5_decrypt( OM_uint32 maj_stat, min_stat; int conf_state, qop_state; - k5printf(("krb5: k5_decrypt: enter\n")); - - if (rc->auth == 1) { - enctok.length = buflen; - enctok.value = buf; + if (rc->conf_fn && rc->conf_fn("kencrypt", rc->datap)) { + auth_debug(1, _("krb5: k5_decrypt: enter\n")); + if (rc->auth == 1) { + enctok.length = buflen; + enctok.value = buf; - k5printf(("krb5: k5_decrypt: decrypting %zu bytes\n", enctok.length)); + auth_debug(1, _("krb5: k5_decrypt: decrypting %zu bytes\n"), enctok.length); - assert(rc->gss_context != GSS_C_NO_CONTEXT); - maj_stat = gss_unseal(&min_stat, rc->gss_context, &enctok, &dectok, + assert(rc->gss_context != GSS_C_NO_CONTEXT); + maj_stat = gss_unseal(&min_stat, rc->gss_context, &enctok, &dectok, &conf_state, &qop_state); - if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { - k5printf(("krb5 decrypt error from %s: %s\n", - rc->hostname, gss_error(maj_stat, min_stat))); - return (-1); + if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { + auth_debug(1, _("krb5 decrypt error from %s: %s\n"), + rc->hostname, gss_error(maj_stat, min_stat)); + return (-1); + } + auth_debug(1, _("krb5: k5_decrypt: give %zu bytes\n"), + dectok.length); + *decbuf = dectok.value; + *decbuflen = dectok.length; + } else { + *decbuf = buf; + *decbuflen = buflen; } - k5printf(("krb5: k5_decrypt: give %zu bytes\n", dectok.length)); - *decbuf = dectok.value; - *decbuflen = dectok.length; + auth_debug(1, _("krb5: k5_decrypt: exit\n")); } else { *decbuf = buf; *decbuflen = buflen; } - k5printf(("krb5: k5_decrypt: exit\n")); return (0); } -#endif /* * check ~/.k5amandahosts to see if this principal is allowed in. If it's @@ -1083,25 +1062,23 @@ krb5_checkuser( char * host, if(strcmp(name, AMANDA_PRINCIPAL) == 0) { return(NULL); } else { - return(vstralloc("does not match compiled in default")); + return(vstrallocf(_("does not match compiled in default"))); } #else struct passwd *pwd; char *ptmp; - char *result = "generic error"; /* default is to not permit */ + char *result = _("generic error"); /* default is to not permit */ FILE *fp = NULL; struct stat sbuf; uid_t localuid; char *line = NULL; char *filehost = NULL, *fileuser = NULL, *filerealm = NULL; - char n1[NUM_STR_SIZE]; - char n2[NUM_STR_SIZE]; assert( host != NULL); assert( name != NULL); if((pwd = getpwnam(CLIENT_LOGIN)) == NULL) { - result = vstralloc("can not find user ", CLIENT_LOGIN, NULL); + result = vstrallocf(_("can not find user %s"), CLIENT_LOGIN); } localuid = pwd->pw_uid; @@ -1112,7 +1089,7 @@ krb5_checkuser( char * host, #endif if(!ptmp) { - result = vstralloc("could not find home directory for ", CLIENT_LOGIN, NULL); + result = vstrallocf(_("could not find home directory for %s"), CLIENT_LOGIN); goto common_exit; } @@ -1125,40 +1102,36 @@ krb5_checkuser( char * host, * the destination user mimicing the .k5login functionality. */ if(strcmp(name, CLIENT_LOGIN) != 0) { - result = vstralloc(name, " does not match ", - CLIENT_LOGIN, NULL); + result = vstrallocf(_("%s does not match %s"), + name, CLIENT_LOGIN); return result; } result = NULL; goto common_exit; } - k5printf(("opening ptmp: %s\n", (ptmp)?ptmp: "NULL!")); + auth_debug(1, _("opening ptmp: %s\n"), (ptmp)?ptmp: "NULL!"); if((fp = fopen(ptmp, "r")) == NULL) { - result = vstralloc("can not open ", ptmp, NULL); + result = vstrallocf(_("can not open %s"), ptmp); return result; } - k5printf(("opened ptmp\n")); + auth_debug(1, _("opened ptmp\n")); if (fstat(fileno(fp), &sbuf) != 0) { - result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL); + result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno)); goto common_exit; } if (sbuf.st_uid != localuid) { - snprintf(n1, SIZEOF(n1), "%ld", (long) sbuf.st_uid); - snprintf(n2, SIZEOF(n2), "%ld", (long) localuid); - result = vstralloc(ptmp, ": ", - "owned by id ", n1, - ", should be ", n2, - NULL); + result = vstrallocf(_("%s is owned by %ld, should be %ld"), + ptmp, (long)sbuf.st_uid, (long)localuid); goto common_exit; } if ((sbuf.st_mode & 077) != 0) { - result = stralloc2(ptmp, - ": incorrect permissions; file must be accessible only by its owner"); + result = vstrallocf( + _("%s: incorrect permissions; file must be accessible only by its owner"), ptmp); goto common_exit; - } + } while ((line = agets(fp)) != NULL) { if (line[0] == '\0') { @@ -1166,9 +1139,6 @@ krb5_checkuser( char * host, continue; } -#if defined(SHOW_SECURITY_DETAIL) /* { */ - k5printf(("%s: processing line: <%s>\n", debug_prefix(NULL), line)); -#endif /* } */ /* if there's more than one column, then it's the host */ if( (filehost = strtok(line, " \t")) == NULL) { amfree(line); @@ -1188,7 +1158,7 @@ krb5_checkuser( char * host, amfree(line); continue; } else { - k5printf(("found a host match\n")); + auth_debug(1, _("found a host match\n")); } if( (filerealm = strchr(fileuser, '@')) != NULL) { @@ -1203,9 +1173,9 @@ krb5_checkuser( char * host, * You likely only get this far if you've turned on cross-realm auth * anyway... */ - k5printf(("comparing %s %s\n", fileuser, name)); + auth_debug(1, _("comparing %s %s\n"), fileuser, name); if(strcmp(fileuser, name) == 0) { - k5printf(("found a match!\n")); + auth_debug(1, _("found a match!\n")); if(realm && filerealm && (strcmp(realm, filerealm)!=0)) { amfree(line); continue; @@ -1216,7 +1186,7 @@ krb5_checkuser( char * host, } amfree(line); } - result = vstralloc("no match in ", ptmp, NULL); + result = vstrallocf(_("no match in %s"), ptmp); common_exit: afclose(fp); @@ -1224,13 +1194,121 @@ common_exit: #endif /* AMANDA_PRINCIPAL */ } -#else - -void krb5_security_dummy(void); +/* + * 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 + */ -void -krb5_security_dummy(void) +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)); } -#endif /* KRB5_SECURITY */