static struct torture_tcase *add_test(struct torture_suite *suite, uint32_t bindoptions, bool keyexchange, bool ntlm2, bool lm_key) { char *name = NULL; struct secret_settings *settings; settings = talloc_zero(suite, struct secret_settings); settings->bindoptions = bindoptions; if (bindoptions == DCERPC_PUSH_BIGENDIAN) name = talloc_strdup(suite, "bigendian"); else if (bindoptions == DCERPC_SEAL) name = talloc_strdup(suite, "seal"); else if (bindoptions == 0) name = talloc_strdup(suite, "none"); else name = talloc_strdup(suite, "unknown"); name = talloc_asprintf_append_buffer(name, " keyexchange:%s", keyexchange?"yes":"no"); settings->keyexchange = keyexchange; name = talloc_asprintf_append_buffer(name, " ntlm2:%s", ntlm2?"yes":"no"); settings->ntlm2 = ntlm2; name = talloc_asprintf_append_buffer(name, " lm_key:%s", lm_key?"yes":"no"); settings->lm_key = lm_key; return torture_suite_add_simple_tcase_const(suite, name, test_secrets, settings); }
static NTSTATUS gpo_prepare_local_store(TALLOC_CTX *mem_ctx, const char *unix_path) { const char *top_dir = lock_path(GPO_CACHE_DIR); char *current_dir; char *tok; current_dir = talloc_strdup(mem_ctx, top_dir); NT_STATUS_HAVE_NO_MEMORY(current_dir); if ((mkdir(top_dir, 0644)) < 0 && errno != EEXIST) { return NT_STATUS_ACCESS_DENIED; } while (next_token_talloc(mem_ctx, &unix_path, &tok, "/")) { if (strequal(tok, GPO_CACHE_DIR)) { break; } } while (next_token_talloc(mem_ctx, &unix_path, &tok, "/")) { current_dir = talloc_asprintf_append_buffer(current_dir, "/%s", tok); NT_STATUS_HAVE_NO_MEMORY(current_dir); if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) { return NT_STATUS_ACCESS_DENIED; } } return NT_STATUS_OK; }
static char *def_tuple(CTX *ctx, struct ir_struct_type *st, bool add_names) { // NOTE: we use the same C type for empty tuples and compounds; should be ok if (st->members_count == 0) return VOID_MANGLE; char *m = get_mangle(ctx, st); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "tuple_"); for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *sm = st->members[n]; mangle_append_sub(&m, def_type(ctx, sm->type)); assert(add_names == (sm->name[0])); if (sm->name) m = talloc_asprintf_append_buffer(m, "n%zd_%s_", strlen(sm->name), sm->name); } if (use_anon_mangle_for_tuples) { char *new_mangle = HT_GET_DEF(dstr, dstr, ctx->tuple_abbrev, m, NULL); if (!new_mangle) { new_mangle = gen_anon_mangle(ctx, "tuple"); HT_INSERT(dstr, dstr, ctx->tuple_abbrev, m, new_mangle); } m = new_mangle; } add_mangle(ctx, st, m); if (!check_redef(ctx, m)) write_struct(ctx, st, m); return m; }
/* encode an ACL in SDDL format */ static char *sddl_encode_acl(TALLOC_CTX *mem_ctx, const struct security_acl *acl, uint32_t flags, const struct dom_sid *domain_sid) { char *sddl; uint32_t i; /* add any ACL flags */ sddl = sddl_flags_to_string(mem_ctx, acl_flags, flags, false); if (sddl == NULL) goto failed; /* now the ACEs, encoded in braces */ for (i=0;i<acl->num_aces;i++) { char *ace = sddl_encode_ace(sddl, &acl->aces[i], domain_sid); if (ace == NULL) goto failed; sddl = talloc_asprintf_append_buffer(sddl, "(%s)", ace); if (sddl == NULL) goto failed; talloc_free(ace); } return sddl; failed: talloc_free(sddl); return NULL; }
/* turn a set of flags into a string */ static char *sddl_flags_to_string(TALLOC_CTX *mem_ctx, const struct flag_map *map, uint32_t flags, bool check_all) { int i; char *s; /* try to find an exact match */ for (i=0;map[i].name;i++) { if (map[i].flag == flags) { return talloc_strdup(mem_ctx, map[i].name); } } s = talloc_strdup(mem_ctx, ""); /* now by bits */ for (i=0;map[i].name;i++) { if ((flags & map[i].flag) != 0) { s = talloc_asprintf_append_buffer(s, "%s", map[i].name); if (s == NULL) goto failed; flags &= ~map[i].flag; } } if (check_all && flags != 0) { goto failed; } return s; failed: talloc_free(s); return NULL; }
/* Return two stable query strings that identify exactly the matched * and unmatched messages currently in thread. If there are no * matched or unmatched messages, the returned buffers will be * NULL. */ static int get_thread_query (notmuch_thread_t *thread, char **matched_out, char **unmatched_out) { notmuch_messages_t *messages; char *escaped = NULL; size_t escaped_len = 0; *matched_out = *unmatched_out = NULL; for (messages = notmuch_thread_get_messages (thread); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { notmuch_message_t *message = notmuch_messages_get (messages); const char *mid = notmuch_message_get_message_id (message); /* Determine which query buffer to extend */ char **buf = notmuch_message_get_flag ( message, NOTMUCH_MESSAGE_FLAG_MATCH) ? matched_out : unmatched_out; /* Add this message's id: query. Since "id" is an exclusive * prefix, it is implicitly 'or'd together, so we only need to * join queries with a space. */ if (make_boolean_term (thread, "id", mid, &escaped, &escaped_len) < 0) return -1; if (*buf) *buf = talloc_asprintf_append_buffer (*buf, " %s", escaped); else *buf = talloc_strdup (thread, escaped); if (!*buf) return -1; } talloc_free (escaped); return 0; }
int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn) { const char *s; char *dn; char *p; int l; if (!domain || !basedn) { return EINVAL; } s = domain; dn = talloc_strdup(memctx, "dc="); while ((p = strchr(s, '.'))) { l = p - s; dn = talloc_asprintf_append_buffer(dn, "%.*s,dc=", l, s); if (!dn) { return ENOMEM; } s = p + 1; } dn = talloc_strdup_append_buffer(dn, s); if (!dn) { return ENOMEM; } for (p=dn; *p; ++p) { *p = tolower(*p); } *basedn = dn; return EOK; }
void winbindd_list_trusted_domains(struct winbindd_cli_state *state) { struct winbindd_tdc_domain *dom_list = NULL; struct winbindd_tdc_domain *d = NULL; size_t num_domains = 0; int extra_data_len = 0; char *extra_data = NULL; int i = 0; DEBUG(3, ("[%5lu]: list trusted domains\n", (unsigned long)state->pid)); if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) { request_error(state); goto done; } extra_data = talloc_strdup(state->mem_ctx, ""); if (extra_data == NULL) { request_error(state); goto done; } for ( i = 0; i < num_domains; i++ ) { struct winbindd_domain *domain; bool is_online = true; d = &dom_list[i]; domain = find_domain_from_name_noinit(d->domain_name); if (domain) { is_online = domain->online; } extra_data = talloc_asprintf_append_buffer( extra_data, "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n", d->domain_name, d->dns_name ? d->dns_name : d->domain_name, sid_string_talloc(state->mem_ctx, &d->sid), get_trust_type_string(d), trust_is_transitive(d) ? "Yes" : "No", trust_is_inbound(d) ? "Yes" : "No", trust_is_outbound(d) ? "Yes" : "No", is_online ? "Online" : "Offline" ); } extra_data_len = strlen(extra_data); if (extra_data_len > 0) { /* Strip the last \n */ extra_data[extra_data_len-1] = '\0'; state->response->extra_data.data = extra_data; state->response->length += extra_data_len; } request_ok(state); done: TALLOC_FREE( dom_list ); }
_PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) { va_list ap; int i; for (i=0;i<ndr->depth;i++) { ndr->private_data = talloc_asprintf_append_buffer( (char *)ndr->private_data, " "); } va_start(ap, format); ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data, format, ap); va_end(ap); ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data, "\n"); }
static void mangle_append_sub(char **s, char *m) { void *p = talloc_parent(*s); assert(p); // Kill prefix, for not making type names not ridiculous long. if (strncmp(m, MANGLE_PREFIX, strlen(MANGLE_PREFIX)) == 0) m = m + strlen(MANGLE_PREFIX); *s = talloc_asprintf_append_buffer(*s, "%zd_%s_", strlen(m), m); }
void wins_hook(struct winsdb_handle *h, const struct winsdb_record *rec, enum wins_hook_action action, const char *wins_hook_script) { uint32_t i, length; int child; char *cmd = NULL; TALLOC_CTX *tmp_mem = NULL; if (!wins_hook_script || !wins_hook_script[0]) return; tmp_mem = talloc_new(h); if (!tmp_mem) goto failed; length = winsdb_addr_list_length(rec->addresses); if (action == WINS_HOOK_MODIFY && length < 1) { action = WINS_HOOK_DELETE; } cmd = talloc_asprintf(tmp_mem, "%s %s %s %02x %ld", wins_hook_script, wins_hook_action_string(action), rec->name->name, rec->name->type, (long int) rec->expire_time); if (!cmd) goto failed; for (i=0; rec->addresses[i]; i++) { cmd = talloc_asprintf_append_buffer(cmd, " %s", rec->addresses[i]->address); if (!cmd) goto failed; } DEBUG(10,("call wins hook '%s'\n", cmd)); /* signal handling in posix really sucks - doing this in a library affects the whole app, but what else to do?? */ signal(SIGCHLD, SIG_IGN); child = fork(); if (child == (pid_t)-1) { goto failed; } if (child == 0) { /* TODO: close file handles */ execl("/bin/sh", "sh", "-c", cmd, NULL); _exit(0); } talloc_free(tmp_mem); return; failed: talloc_free(tmp_mem); DEBUG(0,("FAILED: calling wins hook '%s'\n", wins_hook_script)); }
void websrv_output_headers(struct websrv_context *web, const char *status, struct http_header *headers) { char *s; DATA_BLOB b; struct http_header *hdr; s = talloc_asprintf(web, "HTTP/1.0 %s\r\n", status); if (s == NULL) return; for (hdr = headers; hdr; hdr = hdr->next) { s = talloc_asprintf_append_buffer(s, "%s: %s\r\n", hdr->name, hdr->value); } s = talloc_asprintf_append_buffer(s, "\r\n"); b = web->output.content; web->output.content = data_blob_string_const(s); websrv_output(web, b.data, b.length); data_blob_free(&b); }
/* form a binding string from a binding structure */ _PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b) { char *s = talloc_strdup(mem_ctx, ""); int i; const char *t_name = NULL; if (b->transport != NCA_UNKNOWN) { t_name = derpc_transport_string_by_transport(b->transport); if (!t_name) { return NULL; } } if (!GUID_all_zero(&b->object.uuid)) { s = talloc_asprintf(s, "%s@", GUID_string(mem_ctx, &b->object.uuid)); } if (t_name != NULL) { s = talloc_asprintf_append_buffer(s, "%s:", t_name); if (s == NULL) { return NULL; } } if (b->host) { s = talloc_asprintf_append_buffer(s, "%s", b->host); } if (!b->endpoint && !b->options && !b->flags) { return s; } s = talloc_asprintf_append_buffer(s, "["); if (b->endpoint) { s = talloc_asprintf_append_buffer(s, "%s", b->endpoint); } /* this is a *really* inefficent way of dealing with strings, but this is rarely called and the strings are always short, so I don't care */ for (i=0;b->options && b->options[i];i++) { s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]); if (!s) return NULL; } for (i=0;i<ARRAY_SIZE(ncacn_options);i++) { if (b->flags & ncacn_options[i].flag) { s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name); if (!s) return NULL; } } s = talloc_asprintf_append_buffer(s, "]"); return s; }
/* turn a node status flags field into a string */ static char *node_status_flags(TALLOC_CTX *mem_ctx, uint16_t flags) { char *ret; const char *group = " "; const char *type = "B"; if (flags & NBT_NM_GROUP) { group = "<GROUP>"; } switch (flags & NBT_NM_OWNER_TYPE) { case NBT_NODE_B: type = "B"; break; case NBT_NODE_P: type = "P"; break; case NBT_NODE_M: type = "M"; break; case NBT_NODE_H: type = "H"; break; } ret = talloc_asprintf(mem_ctx, "%s %s", group, type); if (flags & NBT_NM_DEREGISTER) { ret = talloc_asprintf_append_buffer(ret, " <DEREGISTERING>"); } if (flags & NBT_NM_CONFLICT) { ret = talloc_asprintf_append_buffer(ret, " <CONFLICT>"); } if (flags & NBT_NM_ACTIVE) { ret = talloc_asprintf_append_buffer(ret, " <ACTIVE>"); } if (flags & NBT_NM_PERMANENT) { ret = talloc_asprintf_append_buffer(ret, " <PERMANENT>"); } return ret; }
/* encode a security descriptor to SDDL format */ char *sddl_encode(TALLOC_CTX *mem_ctx, const struct security_descriptor *sd, const struct dom_sid *domain_sid) { char *sddl; TALLOC_CTX *tmp_ctx; /* start with a blank string */ sddl = talloc_strdup(mem_ctx, ""); if (sddl == NULL) goto failed; tmp_ctx = talloc_new(mem_ctx); if (sd->owner_sid != NULL) { char *sid = sddl_encode_sid(tmp_ctx, sd->owner_sid, domain_sid); if (sid == NULL) goto failed; sddl = talloc_asprintf_append_buffer(sddl, "O:%s", sid); if (sddl == NULL) goto failed; } if (sd->group_sid != NULL) { char *sid = sddl_encode_sid(tmp_ctx, sd->group_sid, domain_sid); if (sid == NULL) goto failed; sddl = talloc_asprintf_append_buffer(sddl, "G:%s", sid); if (sddl == NULL) goto failed; } if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl != NULL) { char *acl = sddl_encode_acl(tmp_ctx, sd->dacl, sd->type, domain_sid); if (acl == NULL) goto failed; sddl = talloc_asprintf_append_buffer(sddl, "D:%s", acl); if (sddl == NULL) goto failed; } if ((sd->type & SEC_DESC_SACL_PRESENT) && sd->sacl != NULL) { char *acl = sddl_encode_acl(tmp_ctx, sd->sacl, sd->type>>1, domain_sid); if (acl == NULL) goto failed; sddl = talloc_asprintf_append_buffer(sddl, "S:%s", acl); if (sddl == NULL) goto failed; }
/** join a list back to one (shell-like) string; entries * separated by spaces, using quotes where necessary */ _PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) { char *ret = NULL; int i; if (list[0] == NULL) return talloc_strdup(mem_ctx, ""); if (strchr(list[0], ' ') || strlen(list[0]) == 0) ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]); else ret = talloc_strdup(mem_ctx, list[0]); for (i = 1; list[i]; i++) { if (strchr(list[i], ' ') || strlen(list[i]) == 0) ret = talloc_asprintf_append_buffer(ret, "%c\"%s\"", sep, list[i]); else ret = talloc_asprintf_append_buffer(ret, "%c%s", sep, list[i]); } return ret; }
static char * _optimize_tag_query (void *ctx, const char *orig_query_string, const tag_op_list_t *list) { /* This is subtler than it looks. Xapian ignores the '-' operator * at the beginning both queries and parenthesized groups and, * furthermore, the presence of a '-' operator at the beginning of * a group can inhibit parsing of the previous operator. Hence, * the user-provided query MUST appear first, but it is safe to * parenthesize and the exclusion part of the query must not use * the '-' operator (though the NOT operator is fine). */ char *escaped = NULL; size_t escaped_len = 0; char *query_string; const char *join = ""; size_t i; /* Don't optimize if there are no tag changes. */ if (tag_op_list_size (list) == 0) return talloc_strdup (ctx, orig_query_string); /* Build the new query string */ if (strcmp (orig_query_string, "*") == 0) query_string = talloc_strdup (ctx, "("); else query_string = talloc_asprintf (ctx, "( %s ) and (", orig_query_string); for (i = 0; i < tag_op_list_size (list) && query_string; i++) { /* XXX in case of OOM, query_string will be deallocated when * ctx is, which might be at shutdown */ if (make_boolean_term (ctx, "tag", tag_op_list_tag (list, i), &escaped, &escaped_len)) return NULL; query_string = talloc_asprintf_append_buffer ( query_string, "%s%s%s", join, tag_op_list_isremove (list, i) ? "" : "not ", escaped); join = " or "; } if (query_string) query_string = talloc_strdup_append_buffer (query_string, ")"); talloc_free (escaped); return query_string; }
/** * join a list back to one string */ _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator) { char *ret = NULL; int i; if (list[0] == NULL) return talloc_strdup(mem_ctx, ""); ret = talloc_strdup(mem_ctx, list[0]); for (i = 1; list[i]; i++) { ret = talloc_asprintf_append_buffer(ret, "%c%s", separator, list[i]); } return ret; }
static void usersids_recv_sids(struct composite_context *ctx) { struct wbsrv_samba3_call *s3call = talloc_get_type(ctx->async.private_data, struct wbsrv_samba3_call); int i, num_sids; struct dom_sid **sids; char *sids_string; NTSTATUS status; status = wb_cmd_usersids_recv(ctx, s3call, &num_sids, &sids); if (!NT_STATUS_IS_OK(status)) goto done; sids_string = talloc_strdup(s3call, ""); if (sids_string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i<num_sids; i++) { sids_string = talloc_asprintf_append_buffer( sids_string, "%s\n", dom_sid_string(s3call, sids[i])); if (sids_string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } } s3call->response.result = WINBINDD_OK; s3call->response.extra_data.data = sids_string; s3call->response.length += strlen(sids_string); s3call->response.data.num_entries = num_sids; /* Hmmmm. Nasty protocol -- who invented the zeros between the * SIDs? Hmmm. Could have been me -- vl */ while (*sids_string != '\0') { if ((*sids_string) == '\n') { *sids_string = '\0'; } sids_string += 1; } done: wbsrv_samba3_async_epilogue(status, s3call); }
static char *def_array_type(CTX *ctx, struct ir_array_type *at) { char *m = get_mangle(ctx, at); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "arr_"); m = talloc_asprintf_append_buffer(m, "%d_", at->dimension); mangle_append_sub(&m, def_type(ctx, at->item_type)); add_mangle(ctx, at, m); if (!check_redef(ctx, m)) { wf(ctx, "typedef struct %s {", m); indent_in(ctx); wf(ctx, "%s a[%d];", def_type(ctx, at->item_type), at->dimension); indent_out(ctx); wf(ctx, "} %s;", m); } return m; }
static void list_trustdom_recv_doms(struct composite_context *ctx) { struct wbsrv_samba3_call *s3call = talloc_get_type(ctx->async.private_data, struct wbsrv_samba3_call); int i, num_domains; struct wb_dom_info **domains; NTSTATUS status; char *result; status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains, &domains); if (!NT_STATUS_IS_OK(status)) goto done; result = talloc_strdup(s3call, ""); if (result == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i<num_domains; i++) { result = talloc_asprintf_append_buffer( result, "%s\\%s\\%s", domains[i]->name, domains[i]->name, dom_sid_string(s3call, domains[i]->sid)); } if (result == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } s3call->response.result = WINBINDD_OK; if (num_domains > 0) { s3call->response.extra_data.data = result; s3call->response.length += strlen(result)+1; } done: wbsrv_samba3_async_epilogue(status, s3call); }
void merge_playlist_files(struct playlist *pl) { if (!pl->first) return; char *edl = talloc_strdup(NULL, "edl://"); for (struct playlist_entry *e = pl->first; e; e = e->next) { if (e != pl->first) edl = talloc_strdup_append_buffer(edl, ";"); // Escape if needed if (e->filename[strcspn(e->filename, "=%,;\n")] || bstr_strip(bstr0(e->filename)).len != strlen(e->filename)) { // %length% edl = talloc_asprintf_append_buffer(edl, "%%%zd%%", strlen(e->filename)); } edl = talloc_strdup_append_buffer(edl, e->filename); } playlist_clear(pl); playlist_add_file(pl, edl); talloc_free(edl); }
struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r) { struct composite_context *c; struct libnet_UnbecomeDC_state *s; char *tmp_name; c = composite_create(mem_ctx, ctx->event_ctx); if (c == NULL) return NULL; s = talloc_zero(c, struct libnet_UnbecomeDC_state); if (composite_nomem(s, c)) return c; c->private_data = s; s->creq = c; s->libnet = ctx; /* Domain input */ s->domain.dns_name = talloc_strdup(s, r->in.domain_dns_name); if (composite_nomem(s->domain.dns_name, c)) return c; s->domain.netbios_name = talloc_strdup(s, r->in.domain_netbios_name); if (composite_nomem(s->domain.netbios_name, c)) return c; /* Source DSA input */ s->source_dsa.address = talloc_strdup(s, r->in.source_dsa_address); if (composite_nomem(s->source_dsa.address, c)) return c; /* Destination DSA input */ s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name); if (composite_nomem(s->dest_dsa.netbios_name, c)) return c; /* Destination DSA dns_name construction */ tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name); if (composite_nomem(tmp_name, c)) return c; s->dest_dsa.dns_name = talloc_asprintf_append_buffer(tmp_name, ".%s", s->domain.dns_name); if (composite_nomem(s->dest_dsa.dns_name, c)) return c; unbecomeDC_send_cldap(s); return c; }
static void userdomgroups_recv_groups(struct composite_context *ctx) { struct wbsrv_samba3_call *s3call = talloc_get_type(ctx->async.private_data, struct wbsrv_samba3_call); int i, num_sids; struct dom_sid **sids; char *sids_string; NTSTATUS status; status = wb_cmd_userdomgroups_recv(ctx, s3call, &num_sids, &sids); if (!NT_STATUS_IS_OK(status)) goto done; sids_string = talloc_strdup(s3call, ""); if (sids_string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i<num_sids; i++) { sids_string = talloc_asprintf_append_buffer( sids_string, "%s\n", dom_sid_string(s3call, sids[i])); } if (sids_string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } s3call->response.result = WINBINDD_OK; s3call->response.extra_data.data = sids_string; s3call->response.length += strlen(sids_string)+1; s3call->response.data.num_entries = num_sids; done: wbsrv_samba3_async_epilogue(status, s3call); }
enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain, struct winbindd_cli_state *state) { int i; int extra_data_len = 0; char *extra_data; NTSTATUS result; bool have_own_domain = False; struct netr_DomainTrustList trusts; DEBUG(3, ("[%5lu]: list trusted domains\n", (unsigned long)state->pid)); result = domain->methods->trusted_domains(domain, state->mem_ctx, &trusts); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n", nt_errstr(result) )); return WINBINDD_ERROR; } extra_data = talloc_strdup(state->mem_ctx, ""); for (i=0; i<trusts.count; i++) { if (trusts.array[i].sid == NULL) { continue; } if (dom_sid_equal(trusts.array[i].sid, &global_sid_NULL)) { continue; } extra_data = talloc_asprintf_append_buffer( extra_data, "%s\\%s\\%s\\%u\\%u\\%u\n", trusts.array[i].netbios_name, trusts.array[i].dns_name, sid_string_talloc(state->mem_ctx, trusts.array[i].sid), trusts.array[i].trust_flags, (uint32_t)trusts.array[i].trust_type, trusts.array[i].trust_attributes); } /* add our primary domain */ for (i=0; i<trusts.count; i++) { if (strequal(trusts.array[i].netbios_name, domain->name)) { have_own_domain = True; break; } } if (state->request->data.list_all_domains && !have_own_domain) { extra_data = talloc_asprintf_append_buffer( extra_data, "%s\\%s\\%s\n", domain->name, domain->alt_name != NULL ? domain->alt_name : domain->name, sid_string_talloc(state->mem_ctx, &domain->sid)); } extra_data_len = strlen(extra_data); if (extra_data_len > 0) { /* Strip the last \n */ extra_data[extra_data_len-1] = '\0'; state->response->extra_data.data = extra_data; state->response->length += extra_data_len; } return WINBINDD_OK; }
/* miscellaneous tests to try to get a higher test coverage percentage */ static bool test_misc(void) { void *root, *p1; char *p2; double *d; const char *name; printf("test: misc\n# MISCELLANEOUS\n"); root = talloc_new(NULL); p1 = talloc_size(root, 0x7fffffff); torture_assert("misc", !p1, "failed: large talloc allowed\n"); p1 = talloc_strdup(root, "foo"); talloc_increase_ref_count(p1); talloc_increase_ref_count(p1); talloc_increase_ref_count(p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); p2 = talloc_strdup(p1, "foo"); torture_assert("misc", talloc_unlink(root, p2) == -1, "failed: talloc_unlink() of non-reference context should return -1\n"); torture_assert("misc", talloc_unlink(p1, p2) == 0, "failed: talloc_unlink() of parent should succeed\n"); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); name = talloc_set_name(p1, "my name is %s", "foo"); torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", "failed: wrong name after talloc_set_name(my name is foo)"); torture_assert_str_equal("misc", talloc_get_name(p1), name, "failed: wrong name after talloc_set_name(my name is foo)"); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_set_name_const(p1, NULL); torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", "failed: wrong name after talloc_set_name(NULL)"); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); torture_assert("misc", talloc_free(NULL) == -1, "talloc_free(NULL) should give -1\n"); talloc_set_destructor(p1, fail_destructor); torture_assert("misc", talloc_free(p1) == -1, "Failed destructor should cause talloc_free to fail\n"); talloc_set_destructor(p1, NULL); talloc_report(root, stderr); p2 = (char *)talloc_zero_size(p1, 20); torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); talloc_free(p2); torture_assert("misc", talloc_strdup(root, NULL) == NULL, "failed: strdup on NULL should give NULL\n"); p2 = talloc_strndup(p1, "foo", 2); torture_assert("misc", strcmp("fo", p2) == 0, "strndup doesn't work\n"); p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd'); torture_assert("misc", strcmp("food", p2) == 0, "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world"); torture_assert("misc", strcmp("hello world", p2) == 0, "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); talloc_free(p2); d = talloc_array(p1, double, 0x20000000); torture_assert("misc", !d, "failed: integer overflow not detected\n"); d = talloc_realloc(p1, d, double, 0x20000000); torture_assert("misc", !d, "failed: integer overflow not detected\n"); talloc_free(p1); CHECK_BLOCKS("misc", root, 1); p1 = talloc_named(root, 100, "%d bytes", 100); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_unlink(root, p1); p1 = talloc_init("%d bytes", 200); p2 = talloc_asprintf(p1, "my test '%s'", "string"); torture_assert_str_equal("misc", p2, "my test 'string'", "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); CHECK_BLOCKS("misc", p1, 3); CHECK_SIZE("misc", p2, 17); CHECK_BLOCKS("misc", root, 1); talloc_unlink(NULL, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(p1, p2); talloc_report_full(root, stderr); talloc_unlink(root, p2); talloc_report_full(root, stderr); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_unlink(p1, p2); talloc_unlink(root, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(NULL, p2); talloc_report_full(root, stderr); talloc_unlink(root, p2); talloc_report_full(root, stderr); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p2); talloc_unlink(root, p1); /* Test that talloc_unlink is a no-op */ torture_assert("misc", talloc_unlink(root, NULL) == -1, "failed: talloc_unlink(root, NULL) == -1\n"); talloc_report(root, stderr); talloc_report(NULL, stderr); CHECK_SIZE("misc", root, 0); talloc_free(root); CHECK_SIZE("misc", NULL, 0); talloc_enable_null_tracking_no_autofree(); talloc_enable_leak_report(); talloc_enable_leak_report_full(); printf("success: misc\n"); return true; }
static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) { LDAPMessage *entry = NULL; NTSTATUS ret; TALLOC_CTX *memctx; struct idmap_ldap_context *ctx; LDAPMessage *result = NULL; const char *uidNumber; const char *gidNumber; const char **attr_list; char *filter = NULL; bool multi = False; int idx = 0; int bidx = 0; int count; int rc; int i; /* Only do query if we are online */ if (idmap_is_offline()) { return NT_STATUS_FILE_IS_OFFLINE; } ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); memctx = talloc_new(ctx); if ( ! memctx) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER); gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER); attr_list = get_attr_list(memctx, sidmap_attr_list); if ( ! ids[1]) { /* if we are requested just one mapping use the simple filter */ filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_string_talloc(memctx, ids[0]->sid)); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]\n", filter)); } else { /* multiple mappings */ multi = True; } for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; } again: if (multi) { TALLOC_FREE(filter); filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY); CHECK_ALLOC_DONE(filter); bidx = idx; for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { filter = talloc_asprintf_append_buffer(filter, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_string_talloc(memctx, ids[idx]->sid)); CHECK_ALLOC_DONE(filter); } filter = talloc_asprintf_append_buffer(filter, "))"); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]", filter)); } else { bidx = 0; idx = 1; } rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); if (rc != LDAP_SUCCESS) { DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc))); ret = NT_STATUS_UNSUCCESSFUL; goto done; } count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result); if (count == 0) { DEBUG(10, ("NO SIDs found\n")); } for (i = 0; i < count; i++) { char *sidstr = NULL; char *tmp = NULL; enum id_type type; struct id_map *map; struct dom_sid sid; uint32_t id; if (i == 0) { /* first entry */ entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result); } else { /* following ones */ entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry); } if ( ! entry) { DEBUG(2, ("ERROR: Unable to fetch ldap entries " "from results\n")); break; } /* first check if the SID is present */ sidstr = smbldap_talloc_single_attribute( ctx->smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, memctx); if ( ! sidstr) { /* no sid ??, skip entry */ DEBUG(2, ("WARNING SID not found on entry\n")); continue; } if ( ! string_to_sid(&sid, sidstr)) { DEBUG(2, ("ERROR: Invalid SID on entry\n")); TALLOC_FREE(sidstr); continue; } map = idmap_find_map_by_sid(&ids[bidx], &sid); if (!map) { DEBUG(2, ("WARNING: couldn't find entry sid (%s) " "in ids", sidstr)); TALLOC_FREE(sidstr); continue; } /* now try to see if it is a uid, if not try with a gid * (gid is more common, but in case both uidNumber and * gidNumber are returned the SID is mapped to the uid * not the gid) */ type = ID_TYPE_UID; tmp = smbldap_talloc_single_attribute( ctx->smbldap_state->ldap_struct, entry, uidNumber, memctx); if ( ! tmp) { type = ID_TYPE_GID; tmp = smbldap_talloc_single_attribute( ctx->smbldap_state->ldap_struct, entry, gidNumber, memctx); } if ( ! tmp) { /* no ids ?? */ DEBUG(5, ("no uidNumber, " "nor gidNumber attributes found\n")); TALLOC_FREE(sidstr); continue; } id = strtoul(tmp, NULL, 10); if (!idmap_unix_id_is_in_range(id, dom)) { DEBUG(5, ("Requested id (%u) out of range (%u - %u). " "Filtered!\n", id, dom->low_id, dom->high_id)); TALLOC_FREE(sidstr); TALLOC_FREE(tmp); continue; } TALLOC_FREE(tmp); if (map->status == ID_MAPPED) { DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. " "overwriting mapping %s -> %u with %s -> %u\n", (type == ID_TYPE_UID) ? "UID" : "GID", sidstr, map->xid.id, sidstr, id)); } TALLOC_FREE(sidstr); /* mapped */ map->xid.type = type; map->xid.id = id; map->status = ID_MAPPED; DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid), (unsigned long)map->xid.id, map->xid.type)); } /* free the ldap results */ if (result) { ldap_msgfree(result); result = NULL; } if (multi && ids[idx]) { /* still some values to map */ goto again; } /* * try to create new mappings for unmapped sids */ for (i = 0; ids[i]; i++) { if (ids[i]->status != ID_MAPPED) { ids[i]->status = ID_UNMAPPED; if (ids[i]->sid != NULL) { ret = idmap_ldap_new_mapping(dom, ids[i]); if (!NT_STATUS_IS_OK(ret)) { goto done; } } } } ret = NT_STATUS_OK; done: talloc_free(memctx); return ret; }
/** Convert multiple group names into a DNs * * Given an array of group names, builds a filter matching all names, then retrieves all group objects * and stores the DN associated with each group object. * * @param[in] inst rlm_ldap configuration. * @param[in] request Current request. * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect. * @param[in] names to covert to DNs (NULL terminated). * @param[out] out Where to write the DNs. DNs must be freed with ldap_memfree(). Will be NULL terminated. * @param[in] outlen Size of out. * @return One of the RLM_MODULE_* values. */ static rlm_rcode_t rlm_ldap_group_name2dn(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn, char **names, char **out, size_t outlen) { rlm_rcode_t rcode = RLM_MODULE_OK; ldap_rcode_t status; int ldap_errno; unsigned int name_cnt = 0; unsigned int entry_cnt; char const *attrs[] = { NULL }; LDAPMessage *result = NULL, *entry; char **name = names; char **dn = out; char buffer[LDAP_MAX_GROUP_NAME_LEN + 1]; char *filter; *dn = NULL; if (!*names) { return RLM_MODULE_OK; } if (!inst->groupobj_name_attr) { REDEBUG("Told to convert group names to DNs but missing 'group.name_attribute' directive"); return RLM_MODULE_INVALID; } RDEBUG("Converting group name(s) to group DN(s)"); /* * It'll probably only save a few ms in network latency, but it means we can send a query * for the entire group list at once. */ filter = talloc_asprintf(request, "%s%s%s", inst->groupobj_filter ? "(&" : "", inst->groupobj_filter ? inst->groupobj_filter : "", names[0] && names[1] ? "(|" : ""); while (*name) { rlm_ldap_escape_func(request, buffer, sizeof(buffer), *name++, NULL); filter = talloc_asprintf_append_buffer(filter, "(%s=%s)", inst->groupobj_name_attr, buffer); name_cnt++; } filter = talloc_asprintf_append_buffer(filter, "%s%s", inst->groupobj_filter ? ")" : "", names[0] && names[1] ? ")" : ""); status = rlm_ldap_search(inst, request, pconn, inst->groupobj_base_dn, inst->groupobj_scope, filter, attrs, &result); switch (status) { case LDAP_PROC_SUCCESS: break; case LDAP_PROC_NO_RESULT: RDEBUG("Tried to resolve group name(s) to DNs but got no results"); goto finish; default: rcode = RLM_MODULE_FAIL; goto finish; } entry_cnt = ldap_count_entries((*pconn)->handle, result); if (entry_cnt > name_cnt) { REDEBUG("Number of DNs exceeds number of names, group and/or dn should be more restrictive"); rcode = RLM_MODULE_INVALID; goto finish; } if (entry_cnt > (outlen - 1)) { REDEBUG("Number of DNs exceeds limit (%zu)", outlen - 1); rcode = RLM_MODULE_INVALID; goto finish; } if (entry_cnt < name_cnt) { RWDEBUG("Got partial mapping of group names (%i) to DNs (%i), membership information may be incomplete", name_cnt, entry_cnt); } entry = ldap_first_entry((*pconn)->handle, result); if (!entry) { ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno); REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno)); rcode = RLM_MODULE_FAIL; goto finish; } do { *dn = ldap_get_dn((*pconn)->handle, entry); RDEBUG("Got group DN \"%s\"", *dn); dn++; } while((entry = ldap_next_entry((*pconn)->handle, entry))); *dn = NULL; finish: talloc_free(filter); if (result) { ldap_msgfree(result); } /* * Be nice and cleanup the output array if we error out. */ if (rcode != RLM_MODULE_OK) { dn = out; while(*dn) ldap_memfree(*dn++); *dn = NULL; } return rcode; }
static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, struct loadparm_context *lp_ctx, char *buf, int length, void **private1, unsigned int mux_id, void **private2) { DATA_BLOB in; DATA_BLOB out = data_blob(NULL, 0); char *out_base64 = NULL; const char *reply_arg = NULL; struct gensec_ntlm_state { struct gensec_security *gensec_state; const char *set_password; }; struct gensec_ntlm_state *state; struct tevent_context *ev; struct imessaging_context *msg; NTSTATUS nt_status; bool first = false; const char *reply_code; struct cli_credentials *creds; static char *want_feature_list = NULL; static DATA_BLOB session_key; TALLOC_CTX *mem_ctx; if (*private1) { state = (struct gensec_ntlm_state *)*private1; } else { state = talloc_zero(NULL, struct gensec_ntlm_state); if (!state) { mux_printf(mux_id, "BH No Memory\n"); exit(1); } *private1 = state; if (opt_password) { state->set_password = opt_password; } } if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); mux_printf(mux_id, "BH Query invalid\n"); return; } if (strlen(buf) > 3) { if(strncmp(buf, "SF ", 3) == 0) { DEBUG(10, ("Setting flags to negotiate\n")); talloc_free(want_feature_list); want_feature_list = talloc_strndup(state, buf+3, strlen(buf)-3); mux_printf(mux_id, "OK\n"); return; } in = base64_decode_data_blob(buf + 3); } else { in = data_blob(NULL, 0); } if (strncmp(buf, "YR", 2) == 0) { if (state->gensec_state) { talloc_free(state->gensec_state); state->gensec_state = NULL; } } else if ( (strncmp(buf, "OK", 2) == 0)) { /* Just return BH, like ntlm_auth from Samba 3 does. */ mux_printf(mux_id, "BH Command expected\n"); data_blob_free(&in); return; } else if ( (strncmp(buf, "TT ", 3) != 0) && (strncmp(buf, "KK ", 3) != 0) && (strncmp(buf, "AF ", 3) != 0) && (strncmp(buf, "NA ", 3) != 0) && (strncmp(buf, "UG", 2) != 0) && (strncmp(buf, "PW ", 3) != 0) && (strncmp(buf, "GK", 2) != 0) && (strncmp(buf, "GF", 2) != 0)) { DEBUG(1, ("SPNEGO request [%s] invalid\n", buf)); mux_printf(mux_id, "BH SPNEGO request invalid\n"); data_blob_free(&in); return; } ev = s4_event_context_init(state); if (!ev) { exit(1); } mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx"); /* setup gensec */ if (!(state->gensec_state)) { switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case NTLMSSP_CLIENT_1: /* setup the client side */ nt_status = gensec_client_start(NULL, &state->gensec_state, ev, lpcfg_gensec_settings(NULL, lp_ctx)); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); exit(1); } break; case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: { const char *winbind_method[] = { "winbind", NULL }; struct auth4_context *auth_context; msg = imessaging_client_init(state, lpcfg_imessaging_path(state, lp_ctx), ev); if (!msg) { talloc_free(mem_ctx); exit(1); } nt_status = auth_context_create_methods(mem_ctx, winbind_method, ev, msg, lp_ctx, NULL, &auth_context); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); exit(1); } if (!NT_STATUS_IS_OK(gensec_server_start(state, ev, lpcfg_gensec_settings(state, lp_ctx), auth_context, &state->gensec_state))) { talloc_free(mem_ctx); exit(1); } break; } default: talloc_free(mem_ctx); abort(); } creds = cli_credentials_init(state->gensec_state); cli_credentials_set_conf(creds, lp_ctx); if (opt_username) { cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED); } if (opt_domain) { cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED); } if (state->set_password) { cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED); } else { cli_credentials_set_password_callback(creds, get_password); creds->priv_data = (void*)(uintptr_t)mux_id; } if (opt_workstation) { cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); } switch (stdio_helper_mode) { case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: cli_credentials_set_machine_account(creds, lp_ctx); break; default: break; } gensec_set_credentials(state->gensec_state, creds); gensec_want_feature_list(state->gensec_state, want_feature_list); switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case GSS_SPNEGO_SERVER: nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO); if (!in.length) { first = true; } break; case NTLMSSP_CLIENT_1: if (!in.length) { first = true; } /* fall through */ case SQUID_2_5_NTLMSSP: nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP); break; default: talloc_free(mem_ctx); abort(); } if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH GENSEC mech failed to start\n"); talloc_free(mem_ctx); return; } } /* update */ if (strncmp(buf, "PW ", 3) == 0) { state->set_password = talloc_strndup(state, (const char *)in.data, in.length); cli_credentials_set_password(gensec_get_credentials(state->gensec_state), state->set_password, CRED_SPECIFIED); mux_printf(mux_id, "OK\n"); data_blob_free(&in); talloc_free(mem_ctx); return; } if (strncmp(buf, "UG", 2) == 0) { int i; char *grouplist = NULL; struct auth_session_info *session_info; nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("gensec_session_info failed: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status)); data_blob_free(&in); talloc_free(mem_ctx); return; } /* get the string onto the context */ grouplist = talloc_strdup(mem_ctx, ""); for (i=0; i<session_info->security_token->num_sids; i++) { struct security_token *token = session_info->security_token; const char *sidstr = dom_sid_string(session_info, &token->sids[i]); grouplist = talloc_asprintf_append_buffer(grouplist, "%s,", sidstr); } mux_printf(mux_id, "GL %s\n", grouplist); talloc_free(session_info); data_blob_free(&in); talloc_free(mem_ctx); return; } if (strncmp(buf, "GK", 2) == 0) { char *base64_key; DEBUG(10, ("Requested session key\n")); nt_status = gensec_session_key(state->gensec_state, mem_ctx, &session_key); if(!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("gensec_session_key failed: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH No session key\n"); talloc_free(mem_ctx); return; } else { base64_key = base64_encode_data_blob(state, session_key); mux_printf(mux_id, "GK %s\n", base64_key); talloc_free(base64_key); } talloc_free(mem_ctx); return; } if (strncmp(buf, "GF", 2) == 0) { struct ntlmssp_state *ntlmssp_state; uint32_t neg_flags; ntlmssp_state = talloc_get_type(state->gensec_state->private_data, struct ntlmssp_state); neg_flags = ntlmssp_state->neg_flags; DEBUG(10, ("Requested negotiated feature flags\n")); mux_printf(mux_id, "GF 0x%08x\n", neg_flags); return; } nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out); /* don't leak 'bad password'/'no such user' info to the network client */ nt_status = nt_status_squash(nt_status); if (out.length) { out_base64 = base64_encode_data_blob(mem_ctx, out); } else { out_base64 = NULL; } if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { reply_arg = "*"; if (first) { reply_code = "YR"; } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "KK"; } else if (state->gensec_state->gensec_role == GENSEC_SERVER) { reply_code = "TT"; } else { abort(); } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) { reply_code = "BH NT_STATUS_ACCESS_DENIED"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) { reply_code = "BH NT_STATUS_UNSUCCESSFUL"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (!NT_STATUS_IS_OK(nt_status)) { reply_code = "NA"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) { struct auth_session_info *session_info; nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { reply_code = "BH Failed to retrive session info"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status))); } else { reply_code = "AF"; reply_arg = talloc_asprintf(state->gensec_state, "%s%s%s", session_info->info->domain_name, lpcfg_winbind_separator(lp_ctx), session_info->info->account_name); talloc_free(session_info); } } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "AF"; reply_arg = out_base64; } else { abort(); } switch (stdio_helper_mode) { case GSS_SPNEGO_SERVER: mux_printf(mux_id, "%s %s %s\n", reply_code, out_base64 ? out_base64 : "*", reply_arg ? reply_arg : "*"); break; default: if (out_base64) { mux_printf(mux_id, "%s %s\n", reply_code, out_base64); } else if (reply_arg) { mux_printf(mux_id, "%s %s\n", reply_code, reply_arg); } else { mux_printf(mux_id, "%s\n", reply_code); } } talloc_free(mem_ctx); return; }
/** Serialize a cache entry as a humanly readable string * * @param ctx to alloc new string in. Should be a talloc pool a little bigger * than the maximum serialized size of the entry. * @param out Where to write pointer to serialized cache entry. * @param c Cache entry to serialize. * @return 0 on success else -1. */ int cache_serialize(TALLOC_CTX *ctx, char **out, rlm_cache_entry_t *c) { TALLOC_CTX *pairs = NULL; vp_cursor_t cursor; VALUE_PAIR *vp; char *to_store = NULL, *pair; to_store = talloc_asprintf(ctx, "&Cache-Expires = %" PRIu64 "\n&Cache-Created = %" PRIu64 "\n", (uint64_t)c->expires, (uint64_t)c->created); if (!to_store) goto error; /* * It's valid to have an empty cache entry (save allocing the * pairs pool) */ if (!c->control && !c->packet && !c->reply) goto finish; /* * In the majority of cases using these pools reduces the number of mallocs * to two, except in the case where the total serialized pairs length is * greater than the pairs pool, or the total serialized string is greater * than the store pool. */ pairs = talloc_pool(ctx, 512); if (!pairs) { error: talloc_free(pairs); return -1; } if (c->control) { for (vp = fr_cursor_init(&cursor, &c->control); vp; vp = fr_cursor_next(&cursor)) { pair = vp_aprints(pairs, vp, '\''); if (!pair) goto error; to_store = talloc_asprintf_append_buffer(to_store, "&control:%s\n", pair); if (!to_store) goto error; } } if (c->packet) { for (vp = fr_cursor_init(&cursor, &c->packet); vp; vp = fr_cursor_next(&cursor)) { pair = vp_aprints(pairs, vp, '\''); if (!pair) goto error; to_store = talloc_asprintf_append_buffer(to_store, "&%s\n", pair); if (!to_store) goto error; } } if (c->reply) { for (vp = fr_cursor_init(&cursor, &c->reply); vp; vp = fr_cursor_next(&cursor)) { pair = vp_aprints(pairs, vp, '\''); if (!pair) goto error; to_store = talloc_asprintf_append_buffer(to_store, "&reply:%s\n", pair); if (!to_store) goto error; } } finish: talloc_free(pairs); *out = to_store; return 0; }