/* convert a dom_sid to a string */ char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) { char buf[DOM_SID_STR_BUFLEN]; char *result; int len; len = dom_sid_string_buf(sid, buf, sizeof(buf)); if (len+1 > sizeof(buf)) { return talloc_strdup(mem_ctx, "(SID ERR)"); } /* * Avoid calling strlen (via talloc_strdup), we already have * the length */ result = (char *)talloc_memdup(mem_ctx, buf, len+1); if (result == NULL) { return NULL; } /* * beautify the talloc_report output */ talloc_set_name_const(result, result); return result; }
static char *group_mapping_key(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) { char sidstr[DOM_SID_STR_BUFLEN]; int len; len = dom_sid_string_buf(sid, sidstr, sizeof(sidstr)); if (len >= sizeof(sidstr)) { return NULL; } return talloc_asprintf(mem_ctx, "%s%s", GROUP_PREFIX, sidstr); }
void netsamlogon_clear_cached_user(const struct dom_sid *user_sid) { char keystr[DOM_SID_STR_BUFLEN]; if (!netsamlogon_cache_init()) { DEBUG(0,("netsamlogon_clear_cached_user: cannot open " "%s for write!\n", NETSAMLOGON_TDB)); return; } /* Prepare key as DOMAIN-SID/USER-RID string */ dom_sid_string_buf(user_sid, keystr, sizeof(keystr)); DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr)); tdb_delete_bystring(netsamlogon_tdb, keystr); }
char *sid_to_fstring(fstring sidstr_out, const struct dom_sid *sid) { dom_sid_string_buf(sid, sidstr_out, sizeof(fstring)); return sidstr_out; }
bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) { uint8_t dummy = 0; TDB_DATA data = { .dptr = &dummy, .dsize = sizeof(dummy) }; char keystr[DOM_SID_STR_BUFLEN]; bool result = false; struct dom_sid user_sid; TALLOC_CTX *tmp_ctx = talloc_stackframe(); DATA_BLOB blob; enum ndr_err_code ndr_err; struct netsamlogoncache_entry r; int ret; if (!info3) { return false; } if (!netsamlogon_cache_init()) { DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB)); return false; } /* * First write a record with just the domain sid for * netsamlogon_cache_domain_known. Use TDB_INSERT to avoid * overwriting potentially other data. We're just interested * in the existence of that record. */ dom_sid_string_buf(info3->base.domain_sid, keystr, sizeof(keystr)); ret = tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_INSERT); if ((ret == -1) && (tdb_error(netsamlogon_tdb) != TDB_ERR_EXISTS)) { DBG_WARNING("Could not store domain marker for %s: %s\n", keystr, tdb_errorstr(netsamlogon_tdb)); TALLOC_FREE(tmp_ctx); return false; } sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); /* Prepare key as DOMAIN-SID/USER-RID string */ dom_sid_string_buf(&user_sid, keystr, sizeof(keystr)); DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr)); /* Prepare data */ if (info3->base.full_name.string == NULL) { struct netr_SamInfo3 *cached_info3; const char *full_name = NULL; cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid); if (cached_info3 != NULL) { full_name = cached_info3->base.full_name.string; } if (full_name != NULL) { info3->base.full_name.string = talloc_strdup(info3, full_name); } } /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ if (!info3->base.account_name.string) { info3->base.account_name.string = talloc_strdup(info3, username); } r.timestamp = time(NULL); r.info3 = *info3; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r, (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); TALLOC_FREE(tmp_ctx); return false; } data.dsize = blob.length; data.dptr = blob.data; if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) == 0) { result = true; } TALLOC_FREE(tmp_ctx); return result; } /*********************************************************************** Retrieves a netr_SamInfo3 structure from a tdb. Caller must free the user_info struct (talloced memory) ***********************************************************************/ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid) { struct netr_SamInfo3 *info3 = NULL; TDB_DATA data; char keystr[DOM_SID_STR_BUFLEN]; enum ndr_err_code ndr_err; DATA_BLOB blob; struct netsamlogoncache_entry r; if (!netsamlogon_cache_init()) { DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n", NETSAMLOGON_TDB)); return NULL; } /* Prepare key as DOMAIN-SID/USER-RID string */ dom_sid_string_buf(user_sid, keystr, sizeof(keystr)); DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr)); data = tdb_fetch_bystring( netsamlogon_tdb, keystr ); if (!data.dptr) { return NULL; } info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) { goto done; } blob = data_blob_const(data.dptr, data.dsize); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n")); tdb_delete_bystring(netsamlogon_tdb, keystr); TALLOC_FREE(info3); goto done; } if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3, sizeof(r.info3)); done: SAFE_FREE(data.dptr); return info3; } bool netsamlogon_cache_have(const struct dom_sid *sid) { char keystr[DOM_SID_STR_BUFLEN]; bool ok; if (!netsamlogon_cache_init()) { DBG_WARNING("Cannot open %s\n", NETSAMLOGON_TDB); return false; } dom_sid_string_buf(sid, keystr, sizeof(keystr)); ok = tdb_exists(netsamlogon_tdb, string_term_tdb_data(keystr)); return ok; }
/* reply to a ADS style GETDC request */ static NTSTATUS nbtd_netlogon_samlogon( struct nbtd_server *nbtsrv, struct nbt_name *dst_name, const struct socket_address *src, struct nbt_netlogon_packet *netlogon, TALLOC_CTX *mem_ctx, struct nbt_netlogon_response **presponse, char **preply_mailslot) { struct ldb_context *samctx; struct dom_sid *sid = NULL; struct nbt_netlogon_response *response = NULL; char *reply_mailslot = NULL; NTSTATUS status; /* only answer getdc requests on the PDC or LOGON names */ if ((dst_name->type != NBT_NAME_PDC) && (dst_name->type != NBT_NAME_LOGON)) { return NT_STATUS_NOT_SUPPORTED; } samctx = nbtsrv->sam_ctx; if (netlogon->req.logon.sid_size != 0) { sid = &netlogon->req.logon.sid; } reply_mailslot = talloc_strdup( mem_ctx, netlogon->req.logon.mailslot_name); if (reply_mailslot == NULL) { return NT_STATUS_NO_MEMORY; } response = talloc_zero(mem_ctx, struct nbt_netlogon_response); if (response == NULL) { TALLOC_FREE(reply_mailslot); return NT_STATUS_NO_MEMORY; } response->response_type = NETLOGON_SAMLOGON; status = fill_netlogon_samlogon_response( samctx, response, NULL, dst_name->name, sid, NULL, netlogon->req.logon.user_name, netlogon->req.logon.acct_control, src->addr, netlogon->req.logon.nt_version, nbtsrv->task->lp_ctx, &response->data.samlogon, false); if (!NT_STATUS_IS_OK(status)) { char buf[DOM_SID_STR_BUFLEN]; dom_sid_string_buf(sid, buf, sizeof(buf)); DBG_NOTICE("NBT netlogon query failed domain=%s sid=%s " "version=%d - %s\n", dst_name->name, buf, netlogon->req.logon.nt_version, nt_errstr(status)); TALLOC_FREE(reply_mailslot); TALLOC_FREE(response); return status; } *presponse = response; *preply_mailslot = reply_mailslot; return NT_STATUS_OK; }