From ca12257f5911fce691d4ca658ae2f7f66907f3dd Mon Sep 17 00:00:00 2001 From: Paul Park Date: Fri, 28 Apr 1995 19:16:55 +0000 Subject: [PATCH] Moved these administrative protocol functions out of libkrb5 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5622 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/kadm/.Sanitize | 37 +++ src/lib/kadm/.cvsignore | 1 + src/lib/kadm/ChangeLog | 9 + src/lib/kadm/Makefile.in | 25 ++ src/lib/kadm/adm_conn.c | 508 ++++++++++++++++++++++++++++++++++++ src/lib/kadm/adm_rw.c | 525 ++++++++++++++++++++++++++++++++++++++ src/lib/kadm/configure.in | 13 + 7 files changed, 1118 insertions(+) create mode 100644 src/lib/kadm/.Sanitize create mode 100644 src/lib/kadm/.cvsignore create mode 100644 src/lib/kadm/ChangeLog create mode 100644 src/lib/kadm/Makefile.in create mode 100644 src/lib/kadm/adm_conn.c create mode 100644 src/lib/kadm/adm_rw.c create mode 100644 src/lib/kadm/configure.in diff --git a/src/lib/kadm/.Sanitize b/src/lib/kadm/.Sanitize new file mode 100644 index 000000000..910645148 --- /dev/null +++ b/src/lib/kadm/.Sanitize @@ -0,0 +1,37 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +.cvsignore +ChangeLog +Makefile.in +adm_conn.c +adm_rw.c +configure.in + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/lib/kadm/.cvsignore b/src/lib/kadm/.cvsignore new file mode 100644 index 000000000..e8c05a6b1 --- /dev/null +++ b/src/lib/kadm/.cvsignore @@ -0,0 +1 @@ +configure diff --git a/src/lib/kadm/ChangeLog b/src/lib/kadm/ChangeLog new file mode 100644 index 000000000..b49092807 --- /dev/null +++ b/src/lib/kadm/ChangeLog @@ -0,0 +1,9 @@ + +Fri Apr 28 09:47:29 EDT 1995 Paul Park (pjpark@mit.edu) + + Create a new library consisting of functions which communicate with + the administrative server here. These modules replace the originals + which used to be in libkrb5. + + adm_rw.c - Remove ntohl/htonl in favor of byte blasting. + diff --git a/src/lib/kadm/Makefile.in b/src/lib/kadm/Makefile.in new file mode 100644 index 000000000..53e19f040 --- /dev/null +++ b/src/lib/kadm/Makefile.in @@ -0,0 +1,25 @@ +CFLAGS = $(CCOPTS) $(DEFS) +LDFLAGS = -g + +all:: $(OBJS) + +OBJS= adm_conn.o \ + adm_rw.o + +SRCS= $(srcdir)/adm_conn.c \ + $(srcdir)/adm_rw.c + +libkadm.a: ${OBJS} + $(RM) $@ + $(ARADD) $@ $(OBJS) + $(RANLIB) $@ + $(RM) $(TOPLIBD)/libkadm.a + $(CP) libkadm.a $(BUILDTOP)/lib/libkadm.a + $(RANLIB) $(BUILDTOP)/lib/libkadm.a + +install:: libkadm.a + $(INSTALL_DATA) libkadm.a $(KRB5_LIBDIR)/libkadm.a + $(RANLIB) $(KRB5_LIBDIR)/libkadm.a + +clean:: + $(RM) libkadm.a diff --git a/src/lib/kadm/adm_conn.c b/src/lib/kadm/adm_conn.c new file mode 100644 index 000000000..5761acf7e --- /dev/null +++ b/src/lib/kadm/adm_conn.c @@ -0,0 +1,508 @@ +/* + * lib/kadm/adm_conn.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* + * Routines to contact an administrative protocol server. + */ +#define NEED_SOCKETS +#define NEED_LOWLEVEL_IO +#include "k5-int.h" +#include "adm.h" +#include "adm_proto.h" + +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ + +/* + * Strings + */ +static char *kadm_cache_name_fmt = "FILE:/tmp/tkt_kpw_%d"; + +/* + * kadm_get_ccache() - Initialze a credentials cache. + * + * Cleanup after success by calling krb5_cc_destroy() and krb5_free_principal() + * Allocates new ccache and client. + */ +static krb5_error_code +kadm_get_ccache(kcontext, user, ccache, client) + krb5_context kcontext; + char *user; + krb5_ccache *ccache; + krb5_principal *client; +{ + krb5_error_code kret; + char *name; + int did_malloc = 0; + char new_cache[MAXPATHLEN]; + + /* Initialize. */ + *client = (krb5_principal) NULL; + + /* + * If a name specified, then use that one, else get it from our + * current uid. + */ + if (user) { + name = user; + } + else { +#if HAVE_PWD_H + struct passwd *pw; + + pw = getpwuid(getuid()); + if (pw) { + name = (char *) malloc(strlen(pw->pw_name)+1); + did_malloc = 1; + strcpy(name, pw->pw_name); + } + else { + kret = errno; + goto cleanup; + } +#else /* HAVE_PWD_H */ + kret = ENOENT; + goto cleanup; +#endif /* HAVE_PWD_H */ + } + + /* Parse the name and form our principal */ + if (kret = krb5_parse_name(kcontext, name, client)) + goto cleanup; + + (void) sprintf(new_cache, kadm_cache_name_fmt, getpid()); + if (kret = krb5_cc_resolve(kcontext, new_cache, ccache)) + goto cleanup; + + kret = krb5_cc_initialize(kcontext, *ccache, *client); + + cleanup: + if (did_malloc) + free(name); + + if (kret) { + if (*client) + krb5_free_principal(kcontext, *client); + } + + return(kret); +} + +/* + * kadm_get_creds() - Get initial credentials. + * + * Cleanup after success by calling krb5_free_principal(). + * Allocates new principal for creds->server. + */ +static krb5_error_code +kadm_get_creds(kcontext, ccache, client, creds, prompt, oldpw) + krb5_context kcontext; + krb5_ccache ccache; + krb5_principal client; + krb5_creds *creds; + char *prompt; + char *oldpw; +{ + char *client_name; + krb5_error_code kret; + krb5_address **my_addresses; + int old_pwsize; + + /* Initialize */ + my_addresses = (krb5_address **) NULL; + client_name = (char *) NULL; + + /* Get the string form for our principal */ + if (kret = krb5_unparse_name(kcontext, client, &client_name)) + return(kret); + + if (kret = krb5_os_localaddr(&my_addresses)) + goto cleanup; + + creds->client = client; + /* + * Build server principal name: + * "changepw" is service + * realm name is instance + * realm name is realm name + */ + if (kret = krb5_build_principal_ext(kcontext, + &creds->server, + client->realm.length, + client->realm.data, + strlen(KRB5_ADM_SERVICE_NAME), + KRB5_ADM_SERVICE_NAME, + client->realm.length, + client->realm.data, + 0)) + goto cleanup; + + if (prompt != (char *) NULL) { + /* Read the password */ + old_pwsize = KRB5_ADM_MAX_PASSWORD_LEN; + if (kret = krb5_read_password(kcontext, + prompt, + (char *) NULL, + oldpw, + &old_pwsize)) + goto cleanup; + } + + /* Get our initial ticket */ + kret = krb5_get_in_tkt_with_password(kcontext, + 0, + my_addresses, + NULL, + NULL, + oldpw, + ccache, + creds, + 0); + + cleanup: + if (kret) { + if (creds->server) + krb5_free_principal(kcontext, creds->server); + } + if (my_addresses) + krb5_free_addresses(kcontext, my_addresses); + if (client_name) + krb5_xfree(client_name); + return(kret); +} + +/* + * kadm_contact_server() - Establish a connection to the server. + * + * Cleanup after success by calling close() and free(). + * Opens/connects socket *sockp. Allocates address storage for local/remote. + */ +static krb5_error_code +kadm_contact_server(kcontext, realmp, sockp, local, remote) + krb5_context kcontext; + krb5_data *realmp; + int *sockp; + krb5_address **local; + krb5_address **remote; +{ + struct hostent *remote_host; + struct servent *service; + char **hostlist; + int i, count; + + krb5_error_code kret; + + struct sockaddr_in in_local; + struct sockaddr_in in_remote; + int addr_len; + + /* Initialize */ + hostlist = (char **) NULL; + *sockp = -1; + + /* + * XXX - only know ADDRTYPE_INET. + */ +#ifdef KRB5_USE_INET + *local = (krb5_address *) malloc(sizeof(krb5_address)); + *remote = (krb5_address *) malloc(sizeof(krb5_address)); + if ((*local == NULL) || (*remote == NULL)) { + kret = ENOMEM; + goto cleanup; + } + (*local)->addrtype = (*remote)->addrtype = ADDRTYPE_INET; + (*local)->length = (*remote)->length = sizeof(struct in_addr); + (*local)->contents = (krb5_octet *) malloc(sizeof(struct in_addr)); + (*remote)->contents = (krb5_octet *) malloc(sizeof(struct in_addr)); + if (((*local)->contents == NULL) || ((*remote)->contents == NULL)) { + kret = ENOMEM; + goto cleanup; + } + + if ((service = getservbyname(KRB5_ADM_SERVICE_NAME, "tcp")) == NULL) { + kret = ENOENT; + goto cleanup; + } + in_remote.sin_port = service->s_port; +#endif /* KRB5_USE_INET */ + + if (kret = krb5_get_krbhst(kcontext, realmp, &hostlist)) + goto cleanup; + + /* Now count the number of hosts in the realm */ + count = 0; + for (i=0; hostlist[i]; i++) + count++; + if (count == 0) { + kret = ENOENT; /* something better? */ + goto cleanup; + } + +#ifdef KRB5_USE_INET + /* Now find a suitable host */ + for (i=0; hostlist[i]; i++) { + remote_host = gethostbyname(hostlist[i]); + if (remote_host != (struct hostent *) NULL) { + in_remote.sin_family = remote_host->h_addrtype; + (void) memcpy((char *) &in_remote.sin_addr, + (char *) remote_host->h_addr, + sizeof(in_remote.sin_addr)); + break; + } + } + + /* Open a tcp socket */ + *sockp = socket(PF_INET, SOCK_STREAM, 0); + if (*sockp < 0) { + kret = errno; + goto cleanup; + } + else kret = 0; + + if (connect(*sockp, + (struct sockaddr *) &in_remote, + sizeof(in_remote)) < 0) { + kret = errno; + goto cleanup; + } + memcpy((char *) (*remote)->contents, + (char *) &in_remote.sin_addr, + sizeof(struct in_addr)); + + /* Find out local address */ + addr_len = sizeof(in_local); + if (getsockname(*sockp, (struct sockaddr *) &in_local, &addr_len) < 0) + kret = errno; + else + memcpy((char *) (*local)->contents, + (char *) &in_local.sin_addr, + sizeof(struct in_addr)); +#else /* KRB5_USE_INET */ + kret = ENOENT; +#endif /* KRB5_USE_INET */ + + cleanup: + if (kret) { + if (*sockp >= 0) + close(*sockp); + if (*local && (*local)->contents) + free((*local)->contents); + if (*remote && (*remote)->contents) + free((*remote)->contents); + if (*local) { + memset((char *) (*local), 0, sizeof(krb5_address)); + free(*local); + *local = (krb5_address *) NULL; + } + if (*remote) { + memset((char *) (*remote), 0, sizeof(krb5_address)); + free(*remote); + *remote = (krb5_address *) NULL; + } + } + if (hostlist) + krb5_xfree(hostlist); + return(0); +} + +/* + * kadm_get_auth() - Get authorization context. + * + * Cleanup after success by calling krb5_xfree(). + * New krb5_auth_context allocated in *ctxp + */ +static krb5_error_code +kadm_get_auth(kcontext, ctxp, local, remote) + krb5_context kcontext; + krb5_auth_context **ctxp; + krb5_address *local; + krb5_address *remote; +{ + krb5_auth_con_init(kcontext, ctxp); + krb5_auth_con_setflags(kcontext, *ctxp, + KRB5_AUTH_CONTEXT_RET_SEQUENCE| + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + krb5_auth_con_setaddrs(kcontext, *ctxp, local, remote); + return(0); +} + +/* + * krb5_adm_connect() - Establish the connection to the service. + * + * Errors are not reported by this routine. + * Cleanup after successful invocation must: + * destroy ccache. + * free auth_context + * close socket. + */ +krb5_error_code INTERFACE +krb5_adm_connect(kcontext, user, prompt, opassword, sockp, ctxp, ccachep) + krb5_context kcontext; /* Context handle (In ) */ + char *user; /* User specified (In ) */ + char *prompt; /* Old password prompt (In ) */ + char *opassword; /* Old Password (I/O) */ + int *sockp; /* Socket for conn. (Out) */ + krb5_auth_context **ctxp; /* Auth context (Out) */ + krb5_ccache *ccachep; /* Credentials cache (Out) */ +{ + krb5_error_code kret; + krb5_principal client; + krb5_creds creds; + krb5_data server_realm; + krb5_data request_data, suppl_data; + krb5_data response_data; + krb5_address *local_addr; + krb5_address *remote_addr; + + char *server; + + /* Initialize */ + memset((char *) &creds, 0, sizeof(krb5_creds)); + server = (char *) NULL; + *sockp = -1; + local_addr = remote_addr = (krb5_address *) NULL; + client = (krb5_principal) NULL; + *ctxp = (krb5_auth_context *) NULL; + *ccachep = (krb5_ccache) NULL; + + /* + * Find the appropriate credentials cache and set up our identity. + */ + if (kret = kadm_get_ccache(kcontext, user, ccachep, &client)) + goto cleanup; + + /* + * Get initial credentials. + */ + if (kret = kadm_get_creds(kcontext, + *ccachep, + client, + &creds, + prompt, + opassword)) + goto cleanup; + + /* + * Establish connection to server. + */ + if ((server_realm.data = (char *) malloc(client->realm.length+1)) == + (char *) NULL) + goto cleanup; + + server_realm.length = client->realm.length; + memcpy(server_realm.data, client->realm.data, server_realm.length); + server_realm.data[server_realm.length] = '\0'; + if (kret = kadm_contact_server(kcontext, + &server_realm, + sockp, + &local_addr, + &remote_addr)) + goto cleanup; + + /* + * Obtain our authorization context + */ + if (kret = kadm_get_auth(kcontext, ctxp, local_addr, remote_addr)) + goto cleanup; + + /* + * Format, then send the KRB_AP_REQ + */ + suppl_data.data = NULL; + suppl_data.length = 0; + if (kret = krb5_mk_req_extended(kcontext, + ctxp, + AP_OPTS_MUTUAL_REQUIRED, + &suppl_data, + &creds, + &request_data)) + goto cleanup; + + if (kret = krb5_write_message(kcontext, sockp, &request_data)) + goto cleanup; + + /* + * Now read back the response. + */ + if (kret = krb5_read_message(kcontext, sockp, &response_data)) { + goto cleanup; + } + else { + krb5_ap_rep_enc_part *reply = NULL; + + kret = krb5_rd_rep(kcontext, *ctxp, &response_data, &reply); + if (reply) + krb5_free_ap_rep_enc_part(kcontext, reply); + } + cleanup: + if (server) + free(server); + if (kret) { + if (*ctxp) { + krb5_xfree(*ctxp); + *ctxp = (krb5_auth_context *) NULL; + } + if (*sockp >= 0) { + close(*sockp); + *sockp = -1; + } + if (local_addr && local_addr->contents) + free(local_addr->contents); + if (remote_addr && remote_addr->contents) + free(remote_addr->contents); + if (local_addr) + free(local_addr); + if (remote_addr) + free(remote_addr); + if (creds.server) + krb5_free_principal(kcontext, creds.server); + if (client) + krb5_free_principal(kcontext, client); + if (*ccachep) { + krb5_cc_destroy(kcontext, *ccachep); + *ccachep = (krb5_ccache) NULL; + } + } + return(kret); + +} + +/* + * krb5_adm_disconnect() - Disconnect from the administrative service. + */ +void INTERFACE +krb5_adm_disconnect(kcontext, socketp, auth_context, ccache) + krb5_context kcontext; + int *socketp; + krb5_auth_context *auth_context; + krb5_ccache ccache; +{ + if (ccache) + krb5_cc_destroy(kcontext, ccache); + if (auth_context) + krb5_xfree(auth_context); + if (*socketp >= 0) + close(*socketp); +} + diff --git a/src/lib/kadm/adm_rw.c b/src/lib/kadm/adm_rw.c new file mode 100644 index 000000000..ca35be55f --- /dev/null +++ b/src/lib/kadm/adm_rw.c @@ -0,0 +1,525 @@ +/* + * lib/kadm/adm_rw.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * Routines to engage in the administrative (password changing) protocol. + */ +#define NEED_SOCKETS +#include "k5-int.h" +#include "adm_proto.h" + +/* + * Routines to [de]serialize integers. + * + * kadm_copyin_int32 - Move a 32-bit integer fron network byte order to + * host byte order. + * kadm_copyout_int32 - Move a 32-bit integer from host byte order to + * network byte order. + */ +static void +kadm_copyin_int32(cp, ip) + char *cp; + krb5_int32 *ip; +{ + *ip = (((krb5_int32) ((unsigned char) cp[0]) << 24) + + ((krb5_int32) ((unsigned char) cp[1]) << 16) + + ((krb5_int32) ((unsigned char) cp[2]) << 8) + + ((krb5_int32) ((unsigned char) cp[3]))); +} + +static void +kadm_copyout_int32(outint, cp) + krb5_int32 outint; + char *cp; +{ + cp[0] = (outint >> 24) & 0xff; + cp[1] = (outint >> 16) & 0xff; + cp[2] = (outint >> 8) & 0xff; + cp[3] = outint & 0xff; +} + +/* + * krb5_free_adm_data() - Free data blocks allocated by read_adm... routines. + */ +void INTERFACE +krb5_free_adm_data(kcontext, ncomp, datap) + krb5_context kcontext; + krb5_int32 ncomp; + krb5_data *datap; +{ + int i; + + if (datap) { + for (i=0; i 0)) + krb5_xfree(datap[i].data); + + krb5_xfree(datap); + } +} + +/* + * krb5_send_adm_cmd() - Send an administrative command. + * + * Send a list of data in a KRB_PRIV message. Data takes the format: + * nargs (4 octets in network order) + * arg size 1 (4 octets in network order) + * arg data 1 ("arg size 1" octets) + * . + * . + * . + */ +krb5_error_code INTERFACE +krb5_send_adm_cmd(kcontext, sock, ctx, nargs, arglist) + krb5_context kcontext; /* Context handle (In ) */ + krb5_pointer sock; /* Socket to write to (In ) */ + krb5_auth_context *ctx; /* Auth context (In ) */ + int nargs; /* Number of arguments (In ) */ + krb5_data *arglist; /* Components to write (In ) */ +{ + int writebufsize; + int i; + char *writebuf; + krb5_error_code ret; + krb5_int32 ac_flags; + + /* + * First check that our auth context has the right flags in it. + */ + if (ret = krb5_auth_con_getflags(kcontext, ctx, &ac_flags)) + return(ret); + + if ((ac_flags & (KRB5_AUTH_CONTEXT_RET_SEQUENCE| + KRB5_AUTH_CONTEXT_DO_SEQUENCE)) != + (KRB5_AUTH_CONTEXT_RET_SEQUENCE|KRB5_AUTH_CONTEXT_DO_SEQUENCE)) { + /* XXX - need a better error */ + return(KRB5KRB_AP_ERR_MSG_TYPE); + } + + ret = 0; + /* Calculate write buffer size */ + writebufsize = sizeof(krb5_int32); + for (i=0; i= sizeof(krb5_int32)) { + curr = msg_data.data; + kadm_copyin_int32(curr, nargs); + curr += sizeof(krb5_int32); + + /* Are there any components to copy? */ + if (*nargs > 0) { + + /* Get the memory for the list */ + if (*arglist = (krb5_data *) + malloc((size_t) (*nargs) * sizeof(krb5_data))) { + krb5_data *xarglist; + + xarglist = *arglist; + memset((char *) (xarglist), 0, + (size_t) (*nargs) * sizeof(krb5_data)); + + replyok = 1; + /* Copy out each list entry */ + for (i=0; i<*nargs; i++) { + + /* First get the length of the reply component */ + if (curr + sizeof(krb5_int32) - msg_data.data <= + msg_data.length) { + kadm_copyin_int32(curr, + &xarglist[i].length); + curr += sizeof(krb5_int32); + + /* Then get the memory for the actual data */ + if ((curr + xarglist[i].length - + msg_data.data <= msg_data.length) && + (xarglist[i].data = (char *) + malloc(xarglist[i].length+1))) { + + /* Then copy it out */ + memcpy(xarglist[i].data, + curr, + xarglist[i].length); + curr += xarglist[i].length; + + /* Null terminate for convenience */ + xarglist[i].data[xarglist[i].length] + = '\0'; + } + else { + /* Not enough remaining data. */ + replyok = 0; + break; + } + } + else { + /* Not enough remaining data */ + replyok = 0; + break; + } + } + if (!replyok) + krb5_free_adm_data(kcontext, *nargs, *arglist); + } + } + else { + if (*nargs == 0) { + *arglist = (krb5_data *) NULL; + replyok = 1; + } + } + } + if (!replyok) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; /* syntax error */ + } + memset(msg_data.data, 0, msg_data.length); + krb5_xfree(msg_data.data); + } + krb5_xfree(read_data.data); + } + return(ret); +} + +/* + * krb5_read_adm_reply() - Read an administrative protocol response. + * + * Expect to read them out in the same format as send_adm_reply shoots them + * in. + * + * It is the caller's responsibility to free the memory allocated for + * the read in component list. + */ +krb5_error_code INTERFACE +krb5_read_adm_reply(kcontext, sock, ctx, cmd_stat, ncomps, complist) + krb5_context kcontext; /* Context handle (In ) */ + krb5_pointer sock; /* Socket to read from (In ) */ + krb5_auth_context *ctx; /* Auth context (In ) */ + krb5_int32 *cmd_stat; /* Command status (Out) */ + krb5_int32 *ncomps; /* # of reply components(Out) */ + krb5_data **complist; /* List of components (Out) */ +{ + krb5_data read_data; + krb5_error_code ret; + krb5_data msg_data; + krb5_replay_data replay_data; + krb5_int32 ac_flags; + + /* + * First check that our auth context has the right flags in it. + */ + if (ret = krb5_auth_con_getflags(kcontext, ctx, &ac_flags)) + return(ret); + + if ((ac_flags & (KRB5_AUTH_CONTEXT_RET_SEQUENCE| + KRB5_AUTH_CONTEXT_DO_SEQUENCE)) != + (KRB5_AUTH_CONTEXT_RET_SEQUENCE|KRB5_AUTH_CONTEXT_DO_SEQUENCE)) { + /* XXX - need a better error */ + return(KRB5KRB_AP_ERR_MSG_TYPE); + } + + if (!(ret = krb5_read_message(kcontext, sock, &read_data))) { + if (!(ret = krb5_rd_priv(kcontext, + ctx, + &read_data, + &msg_data, + &replay_data))) { + char *curr; + int replyok; + int i; + + replyok = 0; + /* We'd better have at least two reply components */ + if (msg_data.length >= (2*sizeof(krb5_int32))) { + curr = msg_data.data; + kadm_copyin_int32(curr, cmd_stat); + curr += sizeof(krb5_int32); + kadm_copyin_int32(curr, ncomps); + curr += sizeof(krb5_int32); + + /* Are there any components to copy? */ + if (*ncomps > 0) { + + /* Get the memory for the list */ + if (*complist = (krb5_data *) + malloc((size_t) ((*ncomps) * sizeof(krb5_data)))) { + krb5_data *xcomplist; + + xcomplist = *complist; + memset((char *) (xcomplist), 0, + (size_t) ((*ncomps) * sizeof(krb5_data))); + + replyok = 1; + /* Copy out each list entry */ + for (i=0; i<*ncomps; i++) { + + /* First get the length of the reply component */ + if (curr + sizeof(krb5_int32) - msg_data.data <= + msg_data.length) { + kadm_copyin_int32(curr, + &xcomplist[i].length); + curr += sizeof(krb5_int32); + + /* Then get the memory for the actual data */ + if ((curr + xcomplist[i].length - + msg_data.data <= msg_data.length) && + (xcomplist[i].data = (char *) + malloc(xcomplist[i].length+1))) { + + /* Then copy it out */ + memcpy(xcomplist[i].data, + curr, + xcomplist[i].length); + curr += xcomplist[i].length; + + /* Null terminate for convenience */ + xcomplist[i].data[xcomplist[i].length] + = '\0'; + } + else { + /* Not enough remaining data. */ + replyok = 0; + break; + } + } + else { + /* Not enough remaining data */ + replyok = 0; + break; + } + } + if (!replyok) + krb5_free_adm_data(kcontext, *ncomps, *complist); + } + } + else { + if (*ncomps == 0) { + *complist = (krb5_data *) NULL; + replyok = 1; + } + } + } + if (!replyok) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; /* syntax error */ + } + memset(msg_data.data, 0, msg_data.length); + krb5_xfree(msg_data.data); + } + krb5_xfree(read_data.data); + } + return(ret); +} diff --git a/src/lib/kadm/configure.in b/src/lib/kadm/configure.in new file mode 100644 index 000000000..e15eed384 --- /dev/null +++ b/src/lib/kadm/configure.in @@ -0,0 +1,13 @@ +AC_INIT(configure.in) +WITH_CCOPTS +CONFIG_RULES +AC_SET_BUILDTOP +AC_PROG_ARCHIVE +AC_PROG_ARCHIVE_ADD +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_HAVE_HEADERS(pwd.h) +AppendRule([all:: libkadm.a]) +KRB_INCLUDE +WITH_KRB5ROOT +V5_AC_OUTPUT_MAKEFILE -- 2.26.2