static gss_client_response *other_error(const char *fmt, ...) { size_t needed; char *msg; gss_client_response *response = NULL; va_list ap, aps; va_start(ap, fmt); va_copy(aps, ap); needed = snprintf(NULL, 0, fmt, aps); va_end(aps); msg = malloc(needed); if (!msg) die1("Memory allocation failed"); vsnprintf(msg, needed, fmt, ap); va_end(ap); response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->message = msg; // TODO: something other than AUTH_GSS_ERROR? response->return_code = AUTH_GSS_ERROR; return response; }
int main(int argc, char* argv[]) { const char* ip; const char* tmp; if (argc < 2) die1(1, "usage: relay-ctrl-check program [arguments]\n"); log_ips = getenv("RELAY_CTRL_LOG_IPS") != 0; log_env = getenv("RELAY_CTRL_LOG_ENV") != 0; if (getenv("RELAYCLIENT") == 0) { expiry = 0; if ((tmp = getenv("RELAY_CTRL_EXPIRY")) != 0) expiry = atol(tmp); if (expiry <= 0) expiry = 900; if ((rc = getenv("RELAY_CTRL_RELAYCLIENT")) == 0) rc = ""; if ((ip = getenv("TCPREMOTEIP")) == 0) warn1("$TCPREMOTEIP not set, not checking IP"); else if (do_chdir(0)) stat_ip(ip); } else { if (log_ips) msg1("$RELAYCLIENT already set, not checking IP"); } execvp(argv[1], argv+1); die1(111, "execution of program failed!\n"); return 111; argc = 0; }
int main(int argc, char* argv[]) { const char* dir; int fd; struct stat s; char fdstr[32]; if (argc < 2) die1(1, "usage: relay-ctrl-chdir program [arguments]\n"); if ((dir = getenv("RELAY_CTRL_DIR")) == 0) die1(111, "$RELAY_CTRL_DIR is not set."); else if ((fd = open(dir, O_RDONLY)) == -1) die3sys(111, "Could not open dir '", dir, "'"); else if (fstat(fd, &s) == -1) die1sys(111, "Could not stat opened file"); else if (!S_ISDIR(s.st_mode)) die3(111, "'", dir, "' is not a directory"); else { fd = move_high(fd); utoa2(fd, fdstr); if (setenv("RELAY_CTRL_DIR_FD", fdstr, 1) == -1) die1(111, "Could not set environment variable"); } execvp(argv[1], argv+1); die1(111, "execution of program failed!\n"); return 111; argc = 0; }
int main(int argc, char* argv[]) { if (argc < 5) usage("Too few parameters"); if (argc > 7) usage("Too many parameters"); logacct = getpwnam(argv[1]); maindir = argv[2]; logdir = argv[3]; if (maindir[0] != '/' || logdir[0] != '/') die1(1, "Directory names must start with /."); cvmpath = argv[4]; if (argc > 5) { ip = argv[5]; if (argc > 6) dochroot = argv[6]; } if (!logacct) die1(1, "Unknown logacct user name"); umask(0); if (mkdir(maindir, 0755) == -1) die1sys(1, "Error creating main directory"); if (chmod(maindir, 01755) == -1) die1sys(1, "Error setting permissions on main directory"); if (mkdir(logdir, 0700) == -1) die1sys(1, "Error creating log directory"); if (chown(logdir, logacct->pw_uid, logacct->pw_gid) == -1) die1sys(1, "Error setting owner on log directory"); if (chdir(maindir) == -1) die1sys(1, "Error changing to main directory"); if (mkdir("log", 0755) == -1) die1sys(1, "Error creating log service directory"); if (mkdir("env", 0755) == -1) die1sys(1, "Error creating env directory"); start_file("run", 0755); obuf_put5s(&conf_out, "#!/bin/sh\n" "exec 2>&1\n" "umask 022\n" "exec \\\n" "tcpserver -DRHv -llocalhost ", ip, " 21 \\\n" "envdir ", maindir, "/env \\\n"); obuf_put7s(&conf_out, "softlimit -m 2000000 \\\n", conf_bin, "/twoftpd-auth \\\n", cvmpath, " \\\n", conf_bin, "/twoftpd-xfer"); end_file(); make_file("log/run", 0755, "#!/bin/sh\n" "exec \\\n" "setuidgid ", logacct->pw_name, " \\\n" "multilog t ", logdir, 0, 0, 0); if (dochroot) make_fileu("env/CHROOT", 1); return 0; }
gss_client_response *gss_error(const char *func, const char *op, OM_uint32 err_maj, OM_uint32 err_min) { OM_uint32 maj_stat, min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; gss_client_response *response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); char *message = NULL; message = calloc(1024, 1); if(message == NULL) die1("Memory allocation failed"); response->message = message; int nleft = 1024; int n; n = snprintf(message, nleft, "%s(%s)", func, op); message += n; nleft -= n; do { maj_stat = gss_display_status (&min_stat, err_maj, GSS_C_GSS_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); if(GSS_ERROR(maj_stat)) break; n = snprintf(message, nleft, ": %.*s", (int)status_string.length, (char*)status_string.value); message += n; nleft -= n; gss_release_buffer(&min_stat, &status_string); maj_stat = gss_display_status (&min_stat, err_min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if(!GSS_ERROR(maj_stat)) { n = snprintf(message, nleft, ": %.*s", (int)status_string.length, (char*)status_string.value); message += n; nleft -= n; gss_release_buffer(&min_stat, &status_string); } } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); return response; }
void wait_inject(void) { int status; if(inject_pid) { if(waitpid(inject_pid, &status, WUNTRACED) == -1) die1sys(111, "Could not wait for qmail-inject to exit"); if(!WIFEXITED(status)) die1(111, "qmail-inject crashed"); if(WEXITSTATUS(status)) die1(111, "qmail-inject exited with an error"); } }
gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min) { OM_uint32 maj_stat, min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char *buf_maj = calloc(512, sizeof(char)); if(buf_maj == NULL) die1("Memory allocation failed"); char *buf_min = calloc(512, sizeof(char)); if(buf_min == NULL) die1("Memory allocation failed"); char *message = NULL; gss_client_response *response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); do { maj_stat = gss_display_status (&min_stat, err_maj, GSS_C_GSS_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); if(GSS_ERROR(maj_stat)) break; strncpy(buf_maj, (char*) status_string.value, 512); gss_release_buffer(&min_stat, &status_string); maj_stat = gss_display_status (&min_stat, err_min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if(!GSS_ERROR(maj_stat)) { strncpy(buf_min, (char*) status_string.value , 512); gss_release_buffer(&min_stat, &status_string); } } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); // Join the strings message = calloc(1026, 1); if(message == NULL) die1("Memory allocation failed"); // Join the two messages sprintf(message, "%s, %s", buf_maj, buf_min); // Free data free(buf_min); free(buf_maj); // Set the message response->message = message; // Return the message return response; }
gss_client_response *authenticate_gss_client_clean(gss_client_state *state) { OM_uint32 min_stat; int ret = AUTH_GSS_COMPLETE; gss_client_response *response = NULL; if(state->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); if(state->server_name != GSS_C_NO_NAME) gss_release_name(&min_stat, &state->server_name); if(state->username != NULL) { free(state->username); state->username = NULL; } if (state->response != NULL) { free(state->response); state->response = NULL; } if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } return response; }
/* char* server_principal_details(const char* service, const char* hostname) { char match[1024]; int match_len = 0; char* result = NULL; int code; krb5_context kcontext; krb5_keytab kt = NULL; krb5_kt_cursor cursor = NULL; krb5_keytab_entry entry; char* pname = NULL; // Generate the principal prefix we want to match snprintf(match, 1024, "%s/%s@", service, hostname); match_len = strlen(match); code = krb5_init_context(&kcontext); if (code) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code)); return NULL; } if ((code = krb5_kt_default(kcontext, &kt))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot get default keytab", code)); goto end; } if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot get sequence cursor from keytab", code)); goto end; } while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) { if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot parse principal name from keytab", code)); goto end; } if (strncmp(pname, match, match_len) == 0) { result = malloc(strlen(pname) + 1); strcpy(result, pname); krb5_free_unparsed_name(kcontext, pname); krb5_free_keytab_entry_contents(kcontext, &entry); break; } krb5_free_unparsed_name(kcontext, pname); krb5_free_keytab_entry_contents(kcontext, &entry); } if (result == NULL) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Principal not found in keytab", -1)); } end: if (cursor) krb5_kt_end_seq_get(kcontext, kt, &cursor); if (kt) krb5_kt_close(kcontext, kt); krb5_free_context(kcontext); return result; } */ gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; gss_client_response *response = NULL; int ret = AUTH_GSS_COMPLETE; state->server_name = GSS_C_NO_NAME; state->context = GSS_C_NO_CONTEXT; state->gss_flags = gss_flags; state->username = NULL; state->response = NULL; // Import server name first name_token.length = strlen(service); name_token.value = (char *)service; maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_import_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } end: if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } return response; }
gss_client_response *authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_client_response *response = NULL; int ret = AUTH_GSS_CONTINUE; // Always clear out the old response if(state->response != NULL) { free(state->response); state->response = NULL; } // If there is a challenge (data from the server) we need to give it to GSS if(challenge && *challenge) { int len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } // Do GSSAPI step maj_stat = gss_unwrap(&min_stat, state->context, &input_token, &output_token, NULL, NULL); if(maj_stat != GSS_S_COMPLETE) { response = gss_error(__func__, "gss_unwrap", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } else { ret = AUTH_GSS_COMPLETE; } // Grab the client response if(output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); gss_release_buffer(&min_stat, &output_token); } end: if(output_token.value) gss_release_buffer(&min_stat, &output_token); if(input_token.value) free(input_token.value); if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }
int main(int argc, char* argv[]) { const char* bitstr; const char* polystr; int bits; int digits; uint64 poly; const char* suffix; int columns; char* end; int i; const char* name; int reflected; if (argc != 5) { msg3("usage: ", program, " NAME BITS POLY [normal|reflected]"); return 1; } name = argv[1]; bitstr = argv[2]; bits = strtol(bitstr, &end, 0); if (*end != 0) die2(1, "Invalid bits value: ", bitstr); if (bits <= 0 || bits > 64) die1(1, "bits must be between 1 and 64"); digits = (bits + 3) / 4; if (bits > 32) suffix = "ULL,"; else if (bits > 16) suffix = "UL,"; else suffix = "U,"; columns = calc_columns(bits, suffix); polystr = argv[3]; poly = strtoull(polystr, &end, 0); if (*end != 0) die2(1, "Invalid poly value: ", polystr); reflected = 0; if (strcasecmp(argv[4], "reflected") == 0) reflected = 1; else if (strcasecmp(argv[4], "normal") != 0) die2(1, "Must be either 'normal' or 'reflected': ", argv[4]); gentab(bits, poly, reflected); obuf_put3s(&outbuf, "#include \"", name, ".h\"\n\n"); obuf_put5s(&outbuf, "const uint", bitstr, " ", name, "_table[256] = {\n"); for (i = 0; i < 256; ++i) { int column = i % columns; if (column == 0) obuf_puts(&outbuf, " "); obuf_puts(&outbuf, "0x"); if (bits > 32) { obuf_putxw(&outbuf, crctab[i]>>32, digits-8, '0'); obuf_putxw(&outbuf, crctab[i] & 0xffffffffUL, 8, '0'); } else
static gss_client_response *krb5_ctx_error(krb5_context context, krb5_error_code problem) { gss_client_response *response = NULL; const char *error_text = krb5_get_error_message(context, problem); response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->message = strdup(error_text); // TODO: something other than AUTH_GSS_ERROR? AUTH_KRB5_ERROR ? response->return_code = AUTH_GSS_ERROR; krb5_free_error_message(context, error_text); return response; }
static gss_client_response *create_krb5_ccache(gss_server_state *state, krb5_context kcontext, krb5_principal princ, krb5_ccache *ccache) { char *ccname = NULL; int fd; krb5_error_code problem; krb5_ccache tmp_ccache = NULL; gss_client_response *error = NULL; // TODO: mod_auth_kerb used a temp file under /run/httpd/krbcache. what can we do? ccname = strdup("FILE:/tmp/krb5cc_nodekerberos_XXXXXX"); if (!ccname) die1("Memory allocation failed"); fd = mkstemp(ccname + strlen("FILE:")); if (fd < 0) { error = other_error("mkstemp() failed: %s", strerror(errno)); goto end; } close(fd); problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache); if (problem) { error = krb5_ctx_error(kcontext, problem); goto end; } problem = krb5_cc_initialize(kcontext, tmp_ccache, princ); if (problem) { error = krb5_ctx_error(kcontext, problem); goto end; } state->delegated_credentials_cache = strdup(ccname); // TODO: how/when to cleanup the creds cache file? // TODO: how to expose the credentials expiration time? *ccache = tmp_ccache; tmp_ccache = NULL; end: if (tmp_ccache) krb5_cc_destroy(kcontext, tmp_ccache); if (ccname && error) unlink(ccname); if (ccname) free(ccname); return error; }
static gss_client_response *store_gss_creds(gss_server_state *state) { OM_uint32 maj_stat, min_stat; krb5_principal princ = NULL; krb5_ccache ccache = NULL; krb5_error_code problem; krb5_context context; gss_client_response *response = NULL; problem = krb5_init_context(&context); if (problem) { response = other_error("No auth_data value in request from client"); return response; } problem = krb5_parse_name(context, state->username, &princ); if (problem) { response = krb5_ctx_error(context, problem); goto end; } if ((response = create_krb5_ccache(state, context, princ, &ccache))) { goto end; } maj_stat = gss_krb5_copy_ccache(&min_stat, state->client_creds, ccache); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_krb5_copy_ccache", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } krb5_cc_close(context, ccache); ccache = NULL; response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); // TODO: something other than AUTH_GSS_COMPLETE? response->return_code = AUTH_GSS_COMPLETE; end: if (princ) krb5_free_principal(context, princ); if (ccache) krb5_cc_destroy(context, ccache); krb5_free_context(context); return response; }
int cli_main(int argc, char* argv[]) { nistp224key sec; nistp224key pub; obuf out; str str = {0,0,0}; const char* home; const char* keypath; uskey_path = "secret"; upkey_path = "public"; if (argc > 0) keypath = argv[0]; else { if ((home = getenv("HOME")) == 0) die1(1, "$HOME is not set."); if (chdir(home) != 0) die3sys(1, "Could not change directory to '", home, "'"); mkdir(".srcmd", 0700); keypath = ".srcmd/key"; } mkdir(keypath, 0755); if (chdir(keypath) != 0) die3sys(1, "Could not chdir to '", keypath, "'"); random_key(sec); nistp224wrap(pub, BASEP224, sec); base64_encode_line(sec, sizeof sec, &str); if (!obuf_open(&out, uskey_path, OBUF_CREATE|OBUF_EXCLUSIVE, 0400, 0) || !obuf_putstr(&out, &str) || !obuf_putc(&out, '\n') || !obuf_close(&out)) die3sys(1, "Could not create secret key file '", uskey_path, "'"); str_truncate(&str, 0); base64_encode_line(pub, sizeof pub, &str); if (!obuf_open(&out, upkey_path, OBUF_CREATE|OBUF_EXCLUSIVE, 0444, 0) || !obuf_putstr(&out, &str) || !obuf_putc(&out, '\n') || !obuf_close(&out)) die3sys(1, "Could not create public key file '", upkey_path, "'"); msg3("Your public key is '", str.s, "'"); return 0; argc = 1; }
/* State Machine ----------------------------------------------------------- */ static void mainloop(void) { int state = STATE_DISCONNECTED; while (!exitasap) { debugf(DEBUG_STATE, "{Entering state }s", state_name[state]); switch (state) { case STATE_DISCONNECTED: state = do_negotiating(); break; case STATE_NEGOTIATED: state = do_connecting(); break; case STATE_SENDING: state = do_sending(); break; case STATE_CONNECTED: state = do_connected(); break; case STATE_EXITING: exitasap = 1; break; default: die1(1, "Illegal state"); } } }
int main(int argc, char* argv[]) { struct connection conn; iopoll_fd fds[2]; int selfpipe; int i; msg_debug_init(); testmode = getenv("TESTMODE") != 0; if ((shell_argv = malloc((argc + 3) * sizeof *argv)) == 0) die_oom(111); for (i = 1; i < argc; ++i) shell_argv[i-1] = argv[i]; for (; i < argc + 4; ++i) shell_argv[i-1] = 0; shell_argc = argc - 1; if ((path = getenv("PATH")) == 0) die1(111, "No PATH is set"); if ((devnull = open("/dev/null", O_RDWR)) == -1) die1sys(111, "Could not open \"/dev/null\""); if (!nonblock_on(0)) die1sys(111, "Could not set non-blocking status"); if ((selfpipe = selfpipe_init()) == -1) die1sys(111, "Could not create self-pipe"); init_slots(); connection_init(&conn, 0, 0); fds[0].fd = 0; fds[0].events = IOPOLL_READ; fds[1].fd = selfpipe; fds[1].events = IOPOLL_READ; for (;;) { if (iopoll_restart(fds, 2, -1) == -1) die1sys(111, "Poll failed"); if (fds[0].revents) if (connection_read(&conn, handle_packet) <= 0) break; if (fds[1].revents) { read(selfpipe, &i, 1); handle_child(WNOHANG); } } msg1("Waiting for remaining slots to complete"); while (slots_used > 0) handle_child(0); return 0; }
int main(int argc, char* argv[]) { if ((ip = getenv("TCPREMOTEIP")) == 0 || (ip = validate_ip(ip)) == 0) die1(111, "Must be run from tcp-env or tcpserver."); if ((dir = getenv("RELAY_CTRL_DIR")) == 0) warn1("$RELAY_CTRL_DIR is not set."); else if (is_authenticated()) make_file(ip, argc > 1); if (argc > 1) { execvp(argv[1], argv+1); return 111; } return 0; }
gss_client_response *authenticate_gss_server_clean(gss_server_state *state) { OM_uint32 min_stat; int ret = AUTH_GSS_COMPLETE; gss_client_response *response = NULL; if (state->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); if (state->server_name != GSS_C_NO_NAME) gss_release_name(&min_stat, &state->server_name); if (state->client_name != GSS_C_NO_NAME) gss_release_name(&min_stat, &state->client_name); if (state->server_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&min_stat, &state->server_creds); if (state->client_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&min_stat, &state->client_creds); if (state->username != NULL) { free(state->username); state->username = NULL; } if (state->targetname != NULL) { free(state->targetname); state->targetname = NULL; } if (state->response != NULL) { free(state->response); state->response = NULL; } if (state->delegated_credentials_cache) { // TODO: what about actually destroying the cache? It can't be done now as // the whole point is having it around for the lifetime of the "session" free(state->delegated_credentials_cache); } if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }
/* * Convert a DNS name or numeric IP address into an integer value * (in network byte order). This is more general-purpose than * inet_addr() which maps dotted pair notation to uint. */ struct sockaddr *get_sockaddr(const char *s, int port, struct sockaddr *saddr) { struct sockaddr_in *sin = (struct sockaddr_in *)saddr; int ip; if (isdigit(*s)) { ip = (unsigned int)inet_addr(s); } else { struct hostent *hp = gethostbyname(s); if (hp == 0) die1("Can't translate %s to an address", s); ip = *((unsigned int **)hp->h_addr_list)[0]; } memset((char *)sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_port = htons(port); sin->sin_addr.s_addr = ip; return saddr; }
static void load_keys(const char* server) { str path = {0,0,0}; wrap_str(str_copy4s(&path, keydir, "/servers/", server, ".")); if (!keylist_load_multi(&server_publics, path.s, 0) && !keylist_load_multi(&server_publics, "server.", 0)) die1sys(1, "Could not load server keys"); if (!keylist_load_multi(&client_secrets, "", 0)) { wrap_str(str_copy2s(&path, keydir, "/")); if (!keylist_load_multi(&client_secrets, path.s, 0)) die1sys(1, "Could not load sender keys"); } if (!keylist_exchange_all(&shared_secrets, &server_publics, &client_secrets)) die1(1, "No server keys matched any sender keys"); str_free(&path); }
void load_config(void) { unsigned i; wrap_chdir(qmail_home); wrap_chdir("control"); me = read_line("me"); if(!*me) die1(111, "Could not read control/me"); queuelifetime = read_int("queuelifetime", 604800); now = time(0); lastrun = read_int(opt_run_file, 0); if(extra_rcpt_name && *extra_rcpt_name) { if(strchr(extra_rcpt_name, '@')) extra_rcpt = extra_rcpt_name; else { char* er = malloc(strlen(extra_rcpt_name)+strlen(me)+2); strcpy(er, extra_rcpt_name); strcat(er, "@"); strcat(er, me); extra_rcpt = er; } } else extra_rcpt = 0; if (opt_checkrcpt) load_rcpthosts(); debug3(1, "me='", me, "'"); debug2(1, "queuelifetime=", utoa(queuelifetime)); debug3(1, "extra_rcpt='", extra_rcpt, "'"); debug2(1, "now=", utoa(now)); debug2(1, "lastrun=", utoa(lastrun)); for (i = 0; i < opt_age_count; ++i) debug2(1, "opt_ages[]=", utoa(opt_ages[i])); }
int main ( int argc, char *argv[] ) { int exit_val; fribidi_boolean file_found; char *s; FILE *IN; text_width = 80; do_break = true; do_pad = true; do_mirror = true; do_clean = false; do_reorder_nsm = false; show_input = false; show_visual = true; show_basedir = false; show_ltov = false; show_vtol = false; show_levels = false; char_set = "UTF-8"; bol_text = NULL; eol_text = NULL; input_base_direction = FRIBIDI_PAR_ON; if ((s = (char *) getenv ("COLUMNS"))) { int i; i = atoi (s); if (i > 0) text_width = i; } #define CHARSETDESC 257 #define CAPRTL 258 /* Parse the command line with getopt library */ /* Must set argv[0], getopt uses it to generate error messages */ argv[0] = appname; while (1) { int option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"verbose", 0, 0, 'v'}, {"debug", 0, 0, 'd'}, {"test", 0, 0, 't'}, {"charset", 1, 0, 'c'}, #if FRIBIDI_MAIN_USE_ICONV_H+0 #else {"charsetdesc", 1, 0, CHARSETDESC}, {"caprtl", 0, 0, CAPRTL}, #endif /* FRIBIDI_MAIN_USE_ICONV_H */ {"showinput", 0, (int *) (void *) &show_input, true}, {"nopad", 0, (int *) (void *) &do_pad, false}, {"nobreak", 0, (int *) (void *) &do_break, false}, {"width", 1, 0, 'w'}, {"bol", 1, 0, 'B'}, {"eol", 1, 0, 'E'}, {"nomirror", 0, (int *) (void *) &do_mirror, false}, {"reordernsm", 0, (int *) (void *) &do_reorder_nsm, true}, {"clean", 0, (int *) (void *) &do_clean, true}, {"ltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_LTR}, {"rtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_RTL}, {"wltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_WLTR}, {"wrtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_WRTL}, {"basedir", 0, (int *) (void *) &show_basedir, true}, {"ltov", 0, (int *) (void *) &show_ltov, true}, {"vtol", 0, (int *) (void *) &show_vtol, true}, {"levels", 0, (int *) (void *) &show_levels, true}, {"novisual", 0, (int *) (void *) &show_visual, false}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "hVvdtc:w:B:E:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'h': help (); break; case 'V': version (); break; case 'v': show_basedir = show_ltov = show_vtol = show_levels = true; break; case 'w': text_width = atoi (optarg); if (text_width <= 0) die2 ("invalid screen width `%s'\n", optarg); break; case 'B': bol_text = optarg; break; case 'E': eol_text = optarg; break; case 'd': if (!fribidi_set_debug (true)) die1 ("lib" FRIBIDI " must be compiled with DEBUG option to enable\nturn debug info on.\n"); break; case 't': do_clean = show_input = do_reorder_nsm = true; do_break = false; break; case 'c': char_set = my_fribidi_strdup (optarg); if (!char_set) die1 ("memory allocation failed for char_set!"); break; #if FRIBIDI_MAIN_USE_ICONV_H+0 #else case CAPRTL: char_set = "CapRTL"; break; case CHARSETDESC: char_set = optarg; char_set_num = fribidi_parse_charset (char_set); if (!char_set_num) die2 ("unrecognized character set `%s'\n", char_set); if (!fribidi_char_set_desc (char_set_num)) die2 ("no description available for character set `%s'\n", fribidi_char_set_name (char_set_num)); else printf ("Descriptions for character set %s:\n" "\n" "%s", fribidi_char_set_title (char_set_num), fribidi_char_set_desc (char_set_num)); exit (0); break; #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ case ':': case '?': die2 (NULL, NULL); break; default: break; } } #if FRIBIDI_MAIN_USE_ICONV_H+0 to_ucs4 = iconv_open ("WCHAR_T", char_set); from_ucs4 = iconv_open (char_set, "WCHAR_T"); #else /* !FRIBIDI_MAIN_USE_ICONV_H */ char_set_num = fribidi_parse_charset (char_set); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ #if FRIBIDI_MAIN_USE_ICONV_H+0 if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1)) #else /* !FRIBIDI_MAIN_USE_ICONV_H */ if (!char_set_num) #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ die2 ("unrecognized character set `%s'\n", char_set); fribidi_set_mirroring (do_mirror); fribidi_set_reorder_nsm (do_reorder_nsm); exit_val = 0; file_found = false; while (optind < argc || !file_found) { const char *filename; filename = optind < argc ? argv[optind++] : "-"; file_found = true; /* Open the infile for reading */ if (filename[0] == '-' && !filename[1]) { IN = stdin; } else { IN = fopen (filename, "r"); if (!IN) { fprintf (stderr, "%s: %s: no such file or directory\n", appname, filename); exit_val = 1; continue; } } /* Read and process input one line at a time */ { char S_[MAX_STR_LEN]; int padding_width, break_width; padding_width = show_input ? (text_width - 10) / 2 : text_width; break_width = do_break ? padding_width : 3 * MAX_STR_LEN; while (fgets (S_, sizeof (S_) - 1, IN)) { const char *new_line, *nl_found; FriBidiChar logical[MAX_STR_LEN]; char outstring[MAX_STR_LEN]; FriBidiParType base; FriBidiStrIndex len; nl_found = ""; S_[sizeof (S_) - 1] = 0; len = strlen (S_); /* chop */ if (S_[len - 1] == '\n') { len--; S_[len] = '\0'; new_line = "\n"; } else new_line = ""; /* TODO: handle \r */ #if FRIBIDI_MAIN_USE_ICONV_H+0 { char *st = S_, *ust = (char *) logical; int in_len = (int) len; len = sizeof logical; iconv (to_ucs4, &st, &in_len, &ust, (int *) &len); len = (FriBidiChar *) ust - logical; } #else /* !FRIBIDI_MAIN_USE_ICONV_H */ len = fribidi_charset_to_unicode (char_set_num, S_, len, logical); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ { FriBidiChar *visual; FriBidiStrIndex *ltov, *vtol; FriBidiLevel *levels; FriBidiStrIndex new_len; fribidi_boolean log2vis; visual = show_visual ? ALLOCATE (FriBidiChar, len + 1 ) : NULL; ltov = show_ltov ? ALLOCATE (FriBidiStrIndex, len + 1 ) : NULL; vtol = show_vtol ? ALLOCATE (FriBidiStrIndex, len + 1 ) : NULL; levels = show_levels ? ALLOCATE (FriBidiLevel, len + 1 ) : NULL; /* Create a bidi string. */ base = input_base_direction; log2vis = fribidi_log2vis (logical, len, &base, /* output */ visual, ltov, vtol, levels); if (log2vis) { if (show_input) printf ("%-*s => ", padding_width, S_); new_len = len; /* Remove explicit marks, if asked for. */ if (do_clean) len = fribidi_remove_bidi_marks (visual, len, ltov, vtol, levels); if (show_visual) { printf ("%s", nl_found); if (bol_text) printf ("%s", bol_text); /* Convert it to input charset and print. */ { FriBidiStrIndex idx, st; for (idx = 0; idx < len;) { FriBidiStrIndex wid, inlen; wid = break_width; st = idx; #if FRIBIDI_MAIN_USE_ICONV_H+0 #else if (char_set_num != FRIBIDI_CHAR_SET_CAP_RTL) #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ while (wid > 0 && idx < len) { wid -= FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (fribidi_get_bidi_type (visual[idx])) ? 0 : 1; idx++; } #if FRIBIDI_MAIN_USE_ICONV_H+0 #else else while (wid > 0 && idx < len) { wid--; idx++; } #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ if (wid < 0 && idx > st + 1) idx--; inlen = idx - st; #if FRIBIDI_MAIN_USE_ICONV_H+0 { char *str = outstring, *ust = (char *) (visual + st); int in_len = inlen * sizeof visual[0]; new_len = sizeof outstring; iconv (from_ucs4, &ust, &in_len, &str, (int *) &new_len); *str = '\0'; new_len = str - outstring; } #else /* !FRIBIDI_MAIN_USE_ICONV_H */ new_len = fribidi_unicode_to_charset (char_set_num, visual + st, inlen, outstring); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ if (FRIBIDI_IS_RTL (base)) printf ("%*s", (int) (do_pad ? (padding_width + strlen (outstring) - (break_width - wid)) : 0), outstring); else printf ("%s", outstring); if (idx < len) printf ("\n"); } } if (eol_text) printf ("%s", eol_text); nl_found = "\n"; } if (show_basedir) { printf ("%s", nl_found); printf ("Base direction: %s", (FRIBIDI_DIR_TO_LEVEL (base) ? "R" : "L")); nl_found = "\n"; } if (show_ltov) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%ld ", (long) ltov[i]); nl_found = "\n"; } if (show_vtol) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%ld ", (long) vtol[i]); nl_found = "\n"; } if (show_levels) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%d ", (int) levels[i]); nl_found = "\n"; } } else { exit_val = 2; } if (show_visual) free (visual); if (show_ltov) free (ltov); if (show_vtol) free (vtol); if (show_levels) free (levels); } if (*nl_found) printf (new_line); } } } return exit_val; }
/* * username, password: Credentials to validate. Null not allowed * service: Service principal (e.g. HTTP/somehost.example.org) of key * stored in default keytab which will be used to verify KDC. * Empty string (*not* NULL) will bypass KDC verification * return: response->return_code will be * -1 (AUTH_GSS_ERROR) for error, see response->message * 0 for auth fail * 1 for auth ok */ gss_client_response *authenticate_user_krb5_password(const char *username, const char *password, const char *service) { krb5_context context = NULL; krb5_error_code problem; krb5_principal user_principal = NULL; krb5_get_init_creds_opt *opt = NULL; krb5_creds creds; bool auth_ok = false; gss_client_response *response = NULL; if (username == NULL || password == NULL || service == NULL) { return other_error("username, password and service must all be non-null"); } memset(&creds, 0, sizeof(creds)); problem = krb5_init_context(&context); if (problem) { // can't call krb5_ctx_error without a context... response = other_error("unable to initialize krb5 context (%d)", (int)problem); goto out; } problem = krb5_parse_name(context, username, &user_principal); if (problem) { response = krb5_ctx_error(context, problem); goto out; } problem = krb5_get_init_creds_opt_alloc(context, &opt); if (problem) { response = krb5_ctx_error(context, problem); goto out; } problem = krb5_get_init_creds_password(context, &creds, user_principal, (char *)password, NULL, NULL, 0, NULL, opt); switch (problem) { case 0: auth_ok = true; break; case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: /* "expected" error */ auth_ok = false; break; default: /* unexpected error */ response = krb5_ctx_error(context, problem); break; } if (auth_ok && strlen(service) > 0) { response = verify_krb5_kdc(context, &creds, service); } out: krb5_free_cred_contents(context, &creds); if (opt != NULL) { krb5_get_init_creds_opt_free(context, opt); } if (user_principal != NULL) { krb5_free_principal(context, user_principal); } if (context != NULL) { krb5_free_context(context); } if (response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = auth_ok ? 1 : 0; } return response; }
void oom(void) { die1(111, "Out of memory"); }
int cli_main(int argc, char* argv[]) { const char* server_name = 0; const char* env; msg_debug_init(); encr_start(); prep_sender(); service = argv[0]; if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '+') { server_name = argv[1]; ++argv; --argc; } if (argc > 1) load_patterns(argv + 1); if (server_name == 0 && (server_name = getenv("SERVER")) == 0) die1(1, "Server address not named on command line nor in $SERVER"); if (!resolve_ipv4name(server_name, &ip)) die3(1, "Could not resolve '", server_name, "'"); brandom_init(); if ((env = getenv("KEYDIR")) != 0) keydir = env; load_keys(server_name); if ((env = getenv("PORT")) != 0) port = strtoul(env, 0, 10); if (port == 0) port = 11014; if ((sock = socket_udp()) == -1) die1sys(1, "Could not create UDP socket"); if (!socket_connect4(sock, &ip, port)) die1sys(1, "Could not bind socket"); if (!str_ready(&packet, 65535) || !str_ready(&rpacket, 4+4+8+256*5)) die1(1, "Out of memory"); getenvu("ACK_TIMEOUT", &ack_timeout); getenvu("CID_TIMEOUT", &cid_timeout); getenvu("RETRANSMITS", &retransmits); getenvu("READWAIT", &readwait); getenvu("STARTLINES", &startlines); if (getenv("EXITONEOF") != 0) exitoneof = 1; if (getenv("NOFILES") == 0 && getenv("NOFILE") == 0) buffer = buffer_file_init(); else buffer = buffer_nofile_init(); sig_all_catch(sigfn); exitasap = 0; mainloop(); return 0; }
gss_client_response *authenticate_gss_client_step(gss_client_state* state, const char* challenge) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; gss_client_response *response = NULL; // Always clear out the old response if (state->response != NULL) { free(state->response); state->response = NULL; } // If there is a challenge (data from the server) we need to give it to GSS if (challenge && *challenge) { int len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } // Do GSSAPI step maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &state->context, state->server_name, GSS_C_NO_OID, (OM_uint32)state->gss_flags, 0, GSS_C_NO_CHANNEL_BINDINGS, &input_token, NULL, &output_token, NULL, NULL); if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { response = gss_error(__func__, "gss_init_sec_context", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; // Grab the client response to send back to the server if(output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); maj_stat = gss_release_buffer(&min_stat, &output_token); } // Try to get the user name if we have completed all GSS operations if (ret == AUTH_GSS_COMPLETE) { gss_name_t gssuser = GSS_C_NO_NAME; maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL); if(GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_inquire_context", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } gss_buffer_desc name_token; name_token.length = 0; maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL); if(GSS_ERROR(maj_stat)) { if(name_token.value) gss_release_buffer(&min_stat, &name_token); gss_release_name(&min_stat, &gssuser); response = gss_error(__func__, "gss_display_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } else { state->username = (char *)malloc(name_token.length + 1); if(state->username == NULL) die1("Memory allocation failed"); strncpy(state->username, (char*) name_token.value, name_token.length); state->username[name_token.length] = 0; gss_release_buffer(&min_stat, &name_token); gss_release_name(&min_stat, &gssuser); } } end: if(output_token.value) gss_release_buffer(&min_stat, &output_token); if(input_token.value) free(input_token.value); if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }
gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; gss_client_response *response = NULL; char buf[4096], server_conf_flags; unsigned long buf_size; // Always clear out the old response if(state->response != NULL) { free(state->response); state->response = NULL; } if(challenge && *challenge) { int len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } if(user) { // get bufsize server_conf_flags = ((char*) input_token.value)[0]; ((char*) input_token.value)[0] = 0; buf_size = ntohl(*((long *) input_token.value)); free(input_token.value); #ifdef PRINTFS printf("User: %s, %c%c%c\n", user, server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-', server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-', server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'); printf("Maximum GSS token size is %ld\n", buf_size); #endif // agree to terms (hack!) buf_size = htonl(buf_size); // not relevant without integrity/privacy memcpy(buf, &buf_size, 4); buf[0] = GSS_AUTH_P_NONE; // server decides if principal can log in as user strncpy(buf + 4, user, sizeof(buf) - 4); input_token.value = buf; input_token.length = 4 + strlen(user); } // Do GSSAPI wrap maj_stat = gss_wrap(&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, &input_token, NULL, &output_token); if (maj_stat != GSS_S_COMPLETE) { response = gss_error(__func__, "gss_wrap", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } else ret = AUTH_GSS_COMPLETE; // Grab the client response to send back to the server if (output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; gss_release_buffer(&min_stat, &output_token); } end: if (output_token.value) gss_release_buffer(&min_stat, &output_token); if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }
gss_client_response *authenticate_gss_server_init(const char *service, bool constrained_delegation, const char *username, gss_server_state *state) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_COMPLETE; gss_client_response *response = NULL; gss_cred_usage_t usage = GSS_C_ACCEPT; state->context = GSS_C_NO_CONTEXT; state->server_name = GSS_C_NO_NAME; state->client_name = GSS_C_NO_NAME; state->server_creds = GSS_C_NO_CREDENTIAL; state->client_creds = GSS_C_NO_CREDENTIAL; state->username = NULL; state->targetname = NULL; state->response = NULL; state->constrained_delegation = constrained_delegation; state->delegated_credentials_cache = NULL; // Server name may be empty which means we aren't going to create our own creds size_t service_len = strlen(service); if (service_len != 0) { // Import server name first name_token.length = strlen(service); name_token.value = (char *)service; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_import_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } if (state->constrained_delegation) { usage = GSS_C_BOTH; } // Get credentials maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, usage, &state->server_creds, NULL, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_acquire_cred", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } } // If a username was passed, perform the S4U2Self protocol transition to acquire // a credentials from that user as if we had done gss_accept_sec_context. // In this scenario, the passed username is assumed to be already authenticated // by some external mechanism, and we are here to "bootstrap" some gss credentials. // In authenticate_gss_server_step we will bypass the actual authentication step. if (username != NULL) { gss_name_t gss_username; name_token.length = strlen(username); name_token.value = (char *)username; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_USER_NAME, &gss_username); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_import_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } maj_stat = gss_acquire_cred_impersonate_name(&min_stat, state->server_creds, gss_username, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &state->client_creds, NULL, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_acquire_cred_impersonate_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; } gss_release_name(&min_stat, &gss_username); if (response != NULL) { goto end; } // because the username MAY be a "local" username, // we want get the canonical name from the acquired creds. maj_stat = gss_inquire_cred(&min_stat, state->client_creds, &state->client_name, NULL, NULL, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_inquire_cred", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } } end: if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }
gss_client_response *authenticate_gss_server_step(gss_server_state *state, const char *auth_data) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; gss_client_response *response = NULL; // Always clear out the old response if (state->response != NULL) { free(state->response); state->response = NULL; } // we don't need to check the authentication token if S4U2Self protocol // transition was done, because we already have the client credentials. if (state->client_creds == GSS_C_NO_CREDENTIAL) { if (auth_data && *auth_data) { int len; input_token.value = base64_decode(auth_data, &len); input_token.length = len; } else { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->message = strdup("No auth_data value in request from client"); response->return_code = AUTH_GSS_ERROR; goto end; } maj_stat = gss_accept_sec_context(&min_stat, &state->context, state->server_creds, &input_token, GSS_C_NO_CHANNEL_BINDINGS, &state->client_name, NULL, &output_token, NULL, NULL, &state->client_creds); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_accept_sec_context", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } // Grab the server response to send back to the client if (output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); maj_stat = gss_release_buffer(&min_stat, &output_token); } } // Get the user name maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_display_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } state->username = (char *)malloc(output_token.length + 1); strncpy(state->username, (char*) output_token.value, output_token.length); state->username[output_token.length] = 0; // Get the target name if no server creds were supplied if (state->server_creds == GSS_C_NO_CREDENTIAL) { gss_name_t target_name = GSS_C_NO_NAME; maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_inquire_context", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL); if (GSS_ERROR(maj_stat)) { response = gss_error(__func__, "gss_display_name", maj_stat, min_stat); response->return_code = AUTH_GSS_ERROR; goto end; } state->targetname = (char *)malloc(output_token.length + 1); strncpy(state->targetname, (char*) output_token.value, output_token.length); state->targetname[output_token.length] = 0; } if (state->constrained_delegation && state->client_creds != GSS_C_NO_CREDENTIAL) { if ((response = store_gss_creds(state)) != NULL) { goto end; } } ret = AUTH_GSS_COMPLETE; end: if (output_token.length) gss_release_buffer(&min_stat, &output_token); if (input_token.value) free(input_token.value); if(response == NULL) { response = calloc(1, sizeof(gss_client_response)); if(response == NULL) die1("Memory allocation failed"); response->return_code = ret; } // Return the response return response; }