📄 ldap.c
字号:
goto done; servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", machine_name); psp = talloc_asprintf(ctx, "HOST/%s.%s", machine_name, ads->config.realm); strlower_m(&psp[5]); servicePrincipalName[1] = psp; servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", machine_name); psp2 = talloc_asprintf(ctx, "CIFS/%s.%s", machine_name, ads->config.realm); strlower_m(&psp2[5]); servicePrincipalName[3] = psp2; /* Ensure servicePrincipalName[4] and [5] are unique. */ strlower_m(my_fqdn); psp3 = talloc_asprintf(ctx, "CIFS/%s", my_fqdn); strlower_m(&psp3[5]); next_spn = 4; for (i = 0; i < next_spn; i++) { if (strequal(servicePrincipalName[i], psp3)) break; } if (i == next_spn) { servicePrincipalName[next_spn++] = psp3; } psp4 = talloc_asprintf(ctx, "HOST/%s", my_fqdn); strlower_m(&psp4[5]); for (i = 0; i < next_spn; i++) { if (strequal(servicePrincipalName[i], psp4)) break; } if (i == next_spn) { servicePrincipalName[next_spn++] = psp4; } if (!(samAccountName = talloc_asprintf(ctx, "%s$", machine_name))) { goto done; } acct_control = account_type | UF_DONT_EXPIRE_PASSWD;#ifndef ENCTYPE_ARCFOUR_HMAC acct_control |= UF_USE_DES_KEY_ONLY;#endif if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control))) { goto done; } if (!(mods = ads_init_mods(ctx))) { goto done; } if (!exists) { ads_mod_str(ctx, &mods, "cn", machine_name); ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName); ads_mod_str(ctx, &mods, "userAccountControl", controlstr); ads_mod_strlist(ctx, &mods, "objectClass", objectClass); } ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn); ads_mod_str(ctx, &mods, "userPrincipalName", host_upn); ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName); ads_mod_str(ctx, &mods, "operatingSystem", "Samba"); ads_mod_str(ctx, &mods, "operatingSystemVersion", SAMBA_VERSION_STRING); if (!exists) { ret = ads_gen_add(ads, new_dn, mods); } else { ret = ads_gen_mod(ads, new_dn, mods); } if (!ADS_ERR_OK(ret)) { goto done; } /* Do not fail if we can't set security descriptor * it shouldn't be mandatory and probably we just * don't have enough rights to do it. */ if (!exists) { status = ads_set_machine_sd(ads, machine_name, new_dn); if (!ADS_ERR_OK(status)) { DEBUG(0, ("Warning: ads_set_machine_sd: %s\n", ads_errstr(status))); } }done: ads_msgfree(ads, res); talloc_destroy(ctx); return ret;}/* dump a binary result from ldap*/static void dump_binary(const char *field, struct berval **values){ int i, j; for (i=0; values[i]; i++) { printf("%s: ", field); for (j=0; j<values[i]->bv_len; j++) { printf("%02X", (unsigned char)values[i]->bv_val[j]); } printf("\n"); }}static void dump_guid(const char *field, struct berval **values){ int i; UUID_FLAT guid; for (i=0; values[i]; i++) { memcpy(guid.info, values[i]->bv_val, sizeof(guid.info)); printf("%s: %s\n", field, smb_uuid_string_static(smb_uuid_unpack_static(guid))); }}/* dump a sid result from ldap*/static void dump_sid(const char *field, struct berval **values){ int i; for (i=0; values[i]; i++) { DOM_SID sid; sid_parse(values[i]->bv_val, values[i]->bv_len, &sid); printf("%s: %s\n", field, sid_string_static(&sid)); }}/* dump ntSecurityDescriptor*/static void dump_sd(const char *filed, struct berval **values){ prs_struct ps; SEC_DESC *psd = 0; TALLOC_CTX *ctx = 0; if (!(ctx = talloc_init("sec_io_desc"))) return; /* prepare data */ prs_init(&ps, values[0]->bv_len, ctx, UNMARSHALL); prs_copy_data_in(&ps, values[0]->bv_val, values[0]->bv_len); prs_set_offset(&ps,0); /* parse secdesc */ if (!sec_io_desc("sd", &psd, &ps, 1)) { prs_mem_free(&ps); talloc_destroy(ctx); return; } if (psd) ads_disp_sd(psd); prs_mem_free(&ps); talloc_destroy(ctx);}/* dump a string result from ldap*/static void dump_string(const char *field, char **values){ int i; for (i=0; values[i]; i++) { printf("%s: %s\n", field, values[i]); }}/* dump a field from LDAP on stdout used for debugging*/static BOOL ads_dump_field(char *field, void **values, void *data_area){ const struct { const char *name; BOOL string; void (*handler)(const char *, struct berval **); } handlers[] = { {"objectGUID", False, dump_guid}, {"nTSecurityDescriptor", False, dump_sd}, {"dnsRecord", False, dump_binary}, {"objectSid", False, dump_sid}, {"tokenGroups", False, dump_sid}, {NULL, True, NULL} }; int i; if (!field) { /* must be end of an entry */ printf("\n"); return False; } for (i=0; handlers[i].name; i++) { if (StrCaseCmp(handlers[i].name, field) == 0) { if (!values) /* first time, indicate string or not */ return handlers[i].string; handlers[i].handler(field, (struct berval **) values); break; } } if (!handlers[i].name) { if (!values) /* first time, indicate string conversion */ return True; dump_string(field, (char **)values); } return False;}/** * Dump a result from LDAP on stdout * used for debugging * @param ads connection to ads server * @param res Results to dump **/void ads_dump(ADS_STRUCT *ads, void *res){ ads_process_results(ads, res, ads_dump_field, NULL);}/** * Walk through results, calling a function for each entry found. * The function receives a field name, a berval * array of values, * and a data area passed through from the start. The function is * called once with null for field and values at the end of each * entry. * @param ads connection to ads server * @param res Results to process * @param fn Function for processing each result * @param data_area user-defined area to pass to function **/void ads_process_results(ADS_STRUCT *ads, void *res, BOOL(*fn)(char *, void **, void *), void *data_area){ void *msg; TALLOC_CTX *ctx; if (!(ctx = talloc_init("ads_process_results"))) return; for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { char *utf8_field; BerElement *b; for (utf8_field=ldap_first_attribute(ads->ld, (LDAPMessage *)msg,&b); utf8_field; utf8_field=ldap_next_attribute(ads->ld, (LDAPMessage *)msg,b)) { struct berval **ber_vals; char **str_vals, **utf8_vals; char *field; BOOL string; pull_utf8_talloc(ctx, &field, utf8_field); string = fn(field, NULL, data_area); if (string) { utf8_vals = ldap_get_values(ads->ld, (LDAPMessage *)msg, field); str_vals = ads_pull_strvals(ctx, (const char **) utf8_vals); fn(field, (void **) str_vals, data_area); ldap_value_free(utf8_vals); } else { ber_vals = ldap_get_values_len(ads->ld, (LDAPMessage *)msg, field); fn(field, (void **) ber_vals, data_area); ldap_value_free_len(ber_vals); } ldap_memfree(utf8_field); } ber_free(b, 0); talloc_free_children(ctx); fn(NULL, NULL, data_area); /* completed an entry */ } talloc_destroy(ctx);}/** * count how many replies are in a LDAPMessage * @param ads connection to ads server * @param res Results to count * @return number of replies **/int ads_count_replies(ADS_STRUCT *ads, void *res){ return ldap_count_entries(ads->ld, (LDAPMessage *)res);}/** * Join a machine to a realm * Creates the machine account and sets the machine password * @param ads connection to ads server * @param machine name of host to add * @param org_unit Organizational unit to place machine in * @return status of join **/ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name, uint32 account_type, const char *org_unit){ ADS_STATUS status; LDAPMessage *res = NULL; char *machine; /* machine name must be lowercase */ machine = SMB_STRDUP(machine_name); strlower_m(machine); /* status = ads_find_machine_acct(ads, (void **)&res, machine); if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine)); status = ads_leave_realm(ads, machine); if (!ADS_ERR_OK(status)) { DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n", machine, ads->config.realm)); return status; } } */ status = ads_add_machine_acct(ads, machine, account_type, org_unit); if (!ADS_ERR_OK(status)) { DEBUG(0, ("ads_join_realm: ads_add_machine_acct failed (%s): %s\n", machine, ads_errstr(status))); SAFE_FREE(machine); return status; } status = ads_find_machine_acct(ads, (void **)(void *)&res, machine); if (!ADS_ERR_OK(status)) { DEBUG(0, ("ads_join_realm: Host account test failed for machine %s\n", machine)); SAFE_FREE(machine); return status; } SAFE_FREE(machine); ads_msgfree(ads, res); return status;}/** * Delete a machine from the realm * @param ads connection to ads server * @param hostname Machine to remove * @return status of delete **/ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname){ ADS_STATUS status; void *res, *msg; char *hostnameDN, *host; int rc; LDAPControl ldap_control; LDAPControl * pldap_control[2] = {NULL, NULL}; pldap_control[0] = &ldap_control; memset(&ldap_control, 0, sizeof(LDAPControl)); ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID; /* hostname must be lowercase */ host = SMB_STRDUP(hostname); strlower_m(host); status = ads_find_machine_acct(ads, &res, host); if (!ADS_ERR_OK(status)) { DEBUG(0, ("Host account for %s does not exist.\n", host)); return status; } msg = ads_first_entry(ads, res); if (!msg) { return ADS_ERROR_SYSTEM(ENOENT); } hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg); rc = ldap_delete_ext_s(ads->ld, hostnameDN, pldap_control, NULL); if (rc) { DEBUG(3,("ldap_delete_ext_s failed with error code %d\n", rc)); }else { DEBUG(3,("ldap_delete_ext_s succeeded with error code %d\n", rc)); } ads_memfree(ads, hostnameDN); if (rc != LDAP_SUCCESS) { return ADS_ERROR(rc); } status = ads_find_machine_acct(ads, &res, host); if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { DEBUG(0, ("Failed to remove host account.\n")); return status; } free(host); return status;}/** * add machine account to existing security descriptor * @param ads connection to ads server * @param hostname machine to add * @param dn DN of security descriptor * @return status **/ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn){ const char *attrs[] = {"nTSecurityDescriptor", "objectSid", 0}; char *expr = 0; size_t sd_size = 0; struct berval bval = {0, NULL}; prs_struct ps_wire; char *escaped_hostname = escape_ldap_string_alloc(hostname); LDAPMessage *res = 0; LDAPMessage *msg = 0; ADS_MODLIST mods = 0; NTSTATUS status; ADS_STATUS ret; DOM_SID sid; SEC_DESC *psd = NULL; TALLOC_CTX *ctx = NULL; /* Avoid segmentation fault in prs_mem_free if * we have to bail out before prs_init */ ps_wire.is_dynamic = False; if (!ads) return ADS_ERROR(LDAP_SERVER_DOWN); ret = ADS_ERROR(LDAP_SUCCESS); if (!escaped_hostname) { return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } if (asprintf(&expr, "(samAccountName=%s$)", escaped_hostname) == -1) { DEBUG(1, ("ads_set_machine_sd: asprintf failed!\n")); SAFE_FREE(escaped_hostname); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } SAFE_FREE(escaped_hostname); ret = ads_search(ads, (void *) &res, expr, attrs); if (!ADS_ERR_OK(ret)) return ret; if ( !(msg = ads_first_entry(ads, res) )) { ret = ADS_ERROR(LDAP_NO_RESULTS_RETURNED); goto ads_set_sd_error; } if (!ads_pull_sid(ads, msg, attrs[1], &sid)) { ret = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); goto ads_set_sd_error; } if (!(ctx = talloc_init("sec_io_desc"))) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto ads_set_sd_error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -