#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
#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.
*/
#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.
/*
* 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 *);
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.
*/
"KRB5",
krb5_connect,
krb5_accept,
+ sec_get_authenticated_peer_name_hostname,
sec_close,
stream_sendpkt,
stream_recvpkt,
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;
{
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();
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;
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;
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;
struct servent * sp;
int server_socket;
in_port_t my_port, port;
- uid_t euid;
struct tcp_conn * rc = rh->rc;
const char *err;
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,
return -1;
}
- seteuid(euid);
rc->read = rc->write = server_socket;
return -1;
}
+
return 0;
}
+
/*
+
* Negotiate a krb5 gss context from the client end.
*/
static int
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);
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.
}
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;
}
* 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;
}
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;
}
}
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);
* 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;
}
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;
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;
}
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;
}
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;
}
/* 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;
}
* 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;
}
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);
}
{
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);
* 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';
{
#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
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);
}
* 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);
}
*/
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);
}
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);
}
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);
return ((const char *)msg.value);
}
-#ifdef AMANDA_KRB5_ENCRYPT
static int
k5_encrypt(
void *cookie,
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,
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
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;
#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;
}
* 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') {
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);
amfree(line);
continue;
} else {
- k5printf(("found a host match\n"));
+ auth_debug(1, _("found a host match\n"));
}
if( (filerealm = strchr(fileuser, '@')) != NULL) {
* 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;
}
amfree(line);
}
- result = vstralloc("no match in ", ptmp, NULL);
+ result = vstrallocf(_("no match in %s"), ptmp);
common_exit:
afclose(fp);
#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 */