NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx, 
				      TALLOC_CTX *mem_ctx, 
				      const char *service_principal_name, 
				      struct ldb_dn **user_dn,
				      struct ldb_dn **domain_dn) 
{
	WERROR werr;
	struct drsuapi_DsNameInfo1 info1;
	werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
				  DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
				  DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 
				  service_principal_name,
				  &info1);
	if (!W_ERROR_IS_OK(werr)) {
		return werror_to_ntstatus(werr);
	}
	switch (info1.status) {
	case DRSUAPI_DS_NAME_STATUS_OK:
		break;
	case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
	case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
	case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
		return NT_STATUS_NO_SUCH_USER;
	case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
	default:
		return NT_STATUS_UNSUCCESSFUL;
	}

	*user_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);

	if (domain_dn) {
		werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
					  DRSUAPI_DS_NAME_FORMAT_CANONICAL,
					  DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 
					  talloc_asprintf(mem_ctx, "%s/", 
							  info1.dns_domain_name),
					  &info1);
		if (!W_ERROR_IS_OK(werr)) {
			return werror_to_ntstatus(werr);
		}
		switch (info1.status) {
		case DRSUAPI_DS_NAME_STATUS_OK:
			break;
		case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
		case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
		case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
			return NT_STATUS_NO_SUCH_USER;
		case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
		default:
			return NT_STATUS_UNSUCCESSFUL;
		}

		*domain_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);
	}

	return NT_STATUS_OK;
}
WERROR dcesrv_drsuapi_CrackNamesByNameFormat(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
					     const struct drsuapi_DsNameRequest1 *req1,
					     struct drsuapi_DsNameCtr1 **ctr1)
{
	struct drsuapi_DsNameInfo1 *names;
	uint32_t i, count;
	WERROR status;

	*ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1);
	W_ERROR_HAVE_NO_MEMORY(*ctr1);

	count = req1->count;
	names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
	W_ERROR_HAVE_NO_MEMORY(names);

	for (i=0; i < count; i++) {
		status = DsCrackNameOneName(sam_ctx, mem_ctx,
					    req1->format_flags,
					    req1->format_offered,
					    req1->format_desired,
					    req1->names[i].str,
					    &names[i]);
		if (!W_ERROR_IS_OK(status)) {
			return status;
		}
	}

	(*ctr1)->count = count;
	(*ctr1)->array = names;

	return WERR_OK;
}
Exemple #3
0
/* 
  drsuapi_DsCrackNames 
*/
static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
			    struct drsuapi_DsCrackNames *r)
{
	WERROR status;
	struct drsuapi_bind_state *b_state;
	struct dcesrv_handle *h;

	*r->out.level_out = r->in.level;

	DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
	b_state = h->data;

	r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr);
	W_ERROR_HAVE_NO_MEMORY(r->out.ctr);

	switch (r->in.level) {
		case 1: {
			struct drsuapi_DsNameCtr1 *ctr1;
			struct drsuapi_DsNameInfo1 *names;
			int count;
			int i;

			ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
			W_ERROR_HAVE_NO_MEMORY(ctr1);

			count = r->in.req->req1.count;
			names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
			W_ERROR_HAVE_NO_MEMORY(names);

			for (i=0; i < count; i++) {
				status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
							    r->in.req->req1.format_flags,
							    r->in.req->req1.format_offered,
							    r->in.req->req1.format_desired,
							    r->in.req->req1.names[i].str,
							    &names[i]);
				if (!W_ERROR_IS_OK(status)) {
					return status;
				}
			}

			ctr1->count = count;
			ctr1->array = names;
			r->out.ctr->ctr1 = ctr1;

			return WERR_OK;
		}
	}
	
	return WERR_UNKNOWN_LEVEL;
}
Exemple #4
0
/****************************************************************************
 Create an auth_usersupplied_data structure after appropriate mapping.
****************************************************************************/
static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
					 TALLOC_CTX *mem_ctx,
					 const char *default_domain,
					 const struct auth_usersupplied_info *user_info,
					 struct auth_usersupplied_info **user_info_mapped)
{
	char *domain;
	char *account_name;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	WERROR werr;
	struct drsuapi_DsNameInfo1 info1;

	DEBUG(5,("map_user_info_cracknames: Mapping user [%s]\\[%s] from workstation [%s]\n",
		 user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));

	account_name = talloc_strdup(tmp_ctx, user_info->client.account_name);
	if (!account_name) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* use cracknames to work out what domain is being
	   asked for */
	if (strchr_m(user_info->client.account_name, '@') != NULL) {
		werr = DsCrackNameOneName(sam_ctx, tmp_ctx, 0,
					  DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
					  user_info->client.account_name,
					  &info1);
		if (!W_ERROR_IS_OK(werr)) {
			DEBUG(2,("map_user_info: Failed cracknames of account '%s'\n",
				 user_info->client.account_name));
			talloc_free(tmp_ctx);
			return werror_to_ntstatus(werr);
		}
		switch (info1.status) {
		case DRSUAPI_DS_NAME_STATUS_OK:
			break;
		case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> NOT_FOUND\n",
				 user_info->client.account_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> DOMAIN_ONLY\n",
				 user_info->client.account_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> NOT_UNIQUE\n",
				 user_info->client.account_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> RESOLVE_ERROR\n",
				 user_info->client.account_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		default:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> unknown error %u\n",
				 user_info->client.account_name, info1.status));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		}
		/* info1.result_name is in DOMAIN\username
		 * form, which we need to split up into the
		 * user_info_mapped structure
		 */
		domain = talloc_strdup(tmp_ctx, info1.result_name);
		if (domain == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		account_name = strchr_m(domain, '\\');
		if (account_name == NULL) {
			DEBUG(2,("map_user_info: Cracknames of account '%s' gave invalid result '%s'\n",
				 user_info->client.account_name, info1.result_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		}
		*account_name = 0;
		account_name = talloc_strdup(tmp_ctx, account_name+1);
		if (account_name == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
	} else {
		char *domain_name;
		if (user_info->client.domain_name && *user_info->client.domain_name) {
			domain_name = talloc_asprintf(tmp_ctx, "%s\\", user_info->client.domain_name);
		} else {
			domain_name = talloc_strdup(tmp_ctx, default_domain);
		}
		if (domain_name == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
					  domain_name,
					  &info1);
		if (!W_ERROR_IS_OK(werr)) {
			DEBUG(2,("map_user_info: Failed cracknames of domain '%s'\n",
				 domain_name));
			talloc_free(tmp_ctx);
			return werror_to_ntstatus(werr);
		}

		/* we use the account_name as-is, but get the
		 * domain name from cracknames if possible */
		account_name = talloc_strdup(mem_ctx, user_info->client.account_name);
		if (account_name == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		switch (info1.status) {
		case DRSUAPI_DS_NAME_STATUS_OK:
		case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
			domain = talloc_strdup(tmp_ctx, info1.result_name);
			if (domain == NULL) {
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
			if (domain[strlen_m(domain)-1] == '\\') {
				domain[strlen_m(domain)-1] = 0;
			}
			break;
		case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
			/* the domain is unknown - use the
			   default domain */
			domain = talloc_strdup(tmp_ctx, default_domain);
			break;
		case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
			DEBUG(2,("map_user_info: Cracknames of domain '%s' -> NOT_UNIQUE\n",
				 domain_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
			DEBUG(2,("map_user_info: Cracknames of domain '%s' -> RESOLVE_ERROR\n",
				 domain_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		default:
			DEBUG(2,("map_user_info: Cracknames of account '%s' -> unknown error %u\n",
				 domain_name, info1.status));
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		}
		/* domain and account_name are filled in above */
	}

	*user_info_mapped = talloc_zero(mem_ctx, struct auth_usersupplied_info);
	if (!*user_info_mapped) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	if (!talloc_reference(*user_info_mapped, user_info)) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	**user_info_mapped = *user_info;
	(*user_info_mapped)->mapped_state = true;
	(*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain);
	(*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name);
	talloc_free(tmp_ctx);
	if (!(*user_info_mapped)->mapped.domain_name
	    || !(*user_info_mapped)->mapped.account_name) {
		return NT_STATUS_NO_MEMORY;
	}

	return NT_STATUS_OK;
}
Exemple #5
0
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                          uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                          const char *name, struct drsuapi_DsNameInfo1 *info1)
{
    krb5_error_code ret;
    const char *domain_filter = NULL;
    const char *result_filter = NULL;
    struct ldb_dn *name_dn = NULL;

    struct smb_krb5_context *smb_krb5_context = NULL;

    info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    info1->dns_domain_name = NULL;
    info1->result_name = NULL;

    if (!name) {
        return WERR_INVALID_PARAM;
    }

    /* TODO: - fill the correct names in all cases!
     *       - handle format_flags
     */

    /* here we need to set the domain_filter and/or the result_filter */
    switch (format_offered) {
    case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
    {
        int i;
        enum drsuapi_DsNameFormat formats[] = {
            DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL,
            DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY,
            DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
            DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
        };
        WERROR werr;
        for (i=0; i < ARRAY_SIZE(formats); i++) {
            werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1);
            if (!W_ERROR_IS_OK(werr)) {
                return werr;
            }
            if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
                return werr;
            }
        }
        return werr;
    }

    case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
    case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
    {
        char *str, *s, *account;

        if (strlen(name) == 0) {
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        str = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(str);

        if (format_offered == DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX) {
            /* Look backwards for the \n, and replace it with / */
            s = strrchr(str, '\n');
            if (!s) {
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }
            s[0] = '/';
        }

        s = strchr(str, '/');
        if (!s) {
            /* there must be at least one / */
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        s[0] = '\0';
        s++;

        domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(ncName=%s))",
                                        ldb_dn_get_linearized(samdb_dns_domain_to_dn(sam_ctx, mem_ctx, str)));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);

        /* There may not be anything after the domain component (search for the domain itself) */
        if (s[0]) {

            account = strrchr(s, '/');
            if (!account) {
                account = s;
            } else {
                account++;
            }
            account = ldb_binary_encode_string(mem_ctx, account);
            W_ERROR_HAVE_NO_MEMORY(account);
            result_filter = talloc_asprintf(mem_ctx, "(name=%s)",
                                            account);
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
        char *p;
        char *domain;
        const char *account = NULL;

        domain = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(domain);

        p = strchr(domain, '\\');
        if (!p) {
            /* invalid input format */
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        p[0] = '\0';

        if (p[1]) {
            account = &p[1];
        }

        domain_filter = talloc_asprintf(mem_ctx,
                                        "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
                                        ldb_binary_encode_string(mem_ctx, domain));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);
        if (account) {
            result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
                                            ldb_binary_encode_string(mem_ctx, account));
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }

        talloc_free(domain);
        break;
    }

    /* A LDAP DN as a string */
    case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
        domain_filter = NULL;
        name_dn = ldb_dn_new(mem_ctx, sam_ctx, name);
        if (! ldb_dn_validate(name_dn)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        break;
    }

    /* A GUID as a string */
    case DRSUAPI_DS_NAME_FORMAT_GUID: {
        struct GUID guid;
        char *ldap_guid;
        NTSTATUS nt_status;
        domain_filter = NULL;

        nt_status = GUID_from_string(name, &guid);
        if (!NT_STATUS_IS_OK(nt_status)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        ldap_guid = ldap_encode_ndr_GUID(mem_ctx, &guid);
        if (!ldap_guid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectGUID=%s)",
                                        ldap_guid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
        domain_filter = NULL;

        result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
                                        ldb_binary_encode_string(mem_ctx, name),
                                        ldb_binary_encode_string(mem_ctx, name));
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }

    /* A S-1234-5678 style string */
    case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
        struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
        char *ldap_sid;

        domain_filter = NULL;
        if (!sid) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        ldap_sid = ldap_encode_ndr_dom_sid(mem_ctx,
                                           sid);
        if (!ldap_sid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectSid=%s)",
                                        ldap_sid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        /* Ensure we reject compleate junk first */
        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        domain_filter = NULL;

        /* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */
        ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        krb5_free_principal(smb_krb5_context->krb5_context, principal);

        /* The ldb_binary_encode_string() here avoid LDAP filter injection attacks */
        result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(userPrincipalName=%s))",
                                        ldb_binary_encode_string(mem_ctx, unparsed_name));

        free(unparsed_name);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name_short;
        char *service;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret == 0 && principal->name.name_string.len < 2) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_OK;
        }
        ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
                                    KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);

            return dns_domain_from_principal(mem_ctx, smb_krb5_context,
                                             name, info1);
        }

        domain_filter = NULL;

        ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        service = principal->name.name_string.val[0];
        if ((principal->name.name_string.len == 2) && (strcasecmp(service, "host") == 0)) {
            /* the 'cn' attribute is just the leading part of the name */
            char *computer_name;
            computer_name = talloc_strndup(mem_ctx, principal->name.name_string.val[1],
                                           strcspn(principal->name.name_string.val[1], "."));
            if (computer_name == NULL) {
                return WERR_NOMEM;
            }

            result_filter = talloc_asprintf(mem_ctx, "(|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer)))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short),
                                            ldb_binary_encode_string(mem_ctx, computer_name));
        } else {
            result_filter = talloc_asprintf(mem_ctx, "(&(servicePrincipalName=%s)(objectClass=user))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short));
        }
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        free(unparsed_name_short);
        W_ERROR_HAVE_NO_MEMORY(result_filter);

        break;
    }
    default: {
        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        return WERR_OK;
    }

    }

    if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
        return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
                                         name_dn, name, info1);
    }

    return DsCrackNameOneFilter(sam_ctx, mem_ctx,
                                smb_krb5_context,
                                format_flags, format_offered, format_desired,
                                name_dn, name,
                                domain_filter, result_filter,
                                info1);
}
Exemple #6
0
static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                                  struct smb_krb5_context *smb_krb5_context,
                                  uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                                  const char *name, struct drsuapi_DsNameInfo1 *info1)
{
    WERROR wret;
    krb5_error_code ret;
    krb5_principal principal;
    const char *service, *dns_name;
    char *new_service;
    char *new_princ;
    enum drsuapi_DsNameStatus namestatus;

    /* parse principal */
    ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
                                name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
    if (ret) {
        DEBUG(2, ("Could not parse principal: %s: %s",
                  name, smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                          ret, mem_ctx)));
        return WERR_NOMEM;
    }

    /* grab cifs/, http/ etc */

    /* This is checked for in callers, but be safe */
    if (principal->name.name_string.len < 2) {
        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        return WERR_OK;
    }
    service = principal->name.name_string.val[0];
    dns_name = principal->name.name_string.val[1];

    /* MAP it */
    namestatus = LDB_lookup_spn_alias(smb_krb5_context->krb5_context,
                                      sam_ctx, mem_ctx,
                                      service, &new_service);

    if (namestatus == DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
        info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
        info1->dns_domain_name	= talloc_strdup(mem_ctx, dns_name);
        if (!info1->dns_domain_name) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }
        return WERR_OK;
    } else if (namestatus != DRSUAPI_DS_NAME_STATUS_OK) {
        info1->status = namestatus;
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        return WERR_OK;
    }

    /* ooh, very nasty playing around in the Principal... */
    free(principal->name.name_string.val[0]);
    principal->name.name_string.val[0] = strdup(new_service);
    if (!principal->name.name_string.val[0]) {
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        return WERR_NOMEM;
    }

    /* reform principal */
    ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
                                  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &new_princ);

    if (ret) {
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        return WERR_NOMEM;
    }

    wret = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, format_offered, format_desired,
                              new_princ, info1);
    free(new_princ);
    if (W_ERROR_IS_OK(wret) && (info1->status == DRSUAPI_DS_NAME_STATUS_NOT_FOUND)) {
        info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
        info1->dns_domain_name	= talloc_strdup(mem_ctx, dns_name);
        if (!info1->dns_domain_name) {
            wret = WERR_NOMEM;
        }
    }
    krb5_free_principal(smb_krb5_context->krb5_context, principal);
    return wret;
}
static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
				  struct smb_krb5_context *smb_krb5_context,
				  uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
				  enum drsuapi_DsNameFormat format_desired,
				  const char *name, struct drsuapi_DsNameInfo1 *info1)
{
	WERROR wret;
	krb5_error_code ret;
	krb5_principal principal;
	const krb5_data *component;
	const char *service, *dns_name;
	char *new_service;
	char *new_princ;
	enum drsuapi_DsNameStatus namestatus;

	/* parse principal */
	ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, 
				    name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
	if (ret) {
		DEBUG(2, ("Could not parse principal: %s: %s\n",
			  name, smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							   ret, mem_ctx)));
		return WERR_NOMEM;
	}

	/* grab cifs/, http/ etc */

	/* This is checked for in callers, but be safe */
	if (krb5_princ_size(smb_krb5_context->krb5_context, principal) < 2) {
		info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
		krb5_free_principal(smb_krb5_context->krb5_context, principal);
		return WERR_OK;
	}
	component = krb5_princ_component(smb_krb5_context->krb5_context,
					 principal, 0);
	service = (const char *)component->data;
	component = krb5_princ_component(smb_krb5_context->krb5_context,
					 principal, 1);
	dns_name = (const char *)component->data;

	/* MAP it */
	namestatus = LDB_lookup_spn_alias(smb_krb5_context->krb5_context, 
					  sam_ctx, mem_ctx, 
					  service, &new_service);

	if (namestatus == DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
		wret = WERR_OK;
		info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
		info1->dns_domain_name	= talloc_strdup(mem_ctx, dns_name);
		if (!info1->dns_domain_name) {
			wret = WERR_NOMEM;
		}
		krb5_free_principal(smb_krb5_context->krb5_context, principal);
		return wret;
	} else if (namestatus != DRSUAPI_DS_NAME_STATUS_OK) {
		info1->status = namestatus;
		krb5_free_principal(smb_krb5_context->krb5_context, principal);
		return WERR_OK;
	}

	/* reform principal */
	new_princ = talloc_asprintf(mem_ctx, "%s/%s", new_service, dns_name);
	if (!new_princ) {
		krb5_free_principal(smb_krb5_context->krb5_context, principal);
		return WERR_NOMEM;
	}

	wret = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, format_offered, format_desired,
				  new_princ, info1);
	talloc_free(new_princ);
	if (W_ERROR_IS_OK(wret) && (info1->status == DRSUAPI_DS_NAME_STATUS_NOT_FOUND)) {
		info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
		info1->dns_domain_name	= talloc_strdup(mem_ctx, dns_name);
		if (!info1->dns_domain_name) {
			wret = WERR_NOMEM;
		}
	}
	krb5_free_principal(smb_krb5_context->krb5_context, principal);
	return wret;
}
NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx, 
				struct tevent_context *ev_ctx, 
				struct loadparm_context *lp_ctx,
				enum drsuapi_DsNameFormat format_offered,
				const char *name, 
				const char **nt4_domain, const char **nt4_account)
{
	WERROR werr;
	struct drsuapi_DsNameInfo1 info1;
	struct ldb_context *ldb;
	char *p;

	/* Handle anonymous bind */
	if (!name || !*name) {
		*nt4_domain = "";
		*nt4_account = "";
		return NT_STATUS_OK;
	}

	ldb = samdb_connect(mem_ctx, ev_ctx, lp_ctx, system_session(lp_ctx), 0);
	if (ldb == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	werr = DsCrackNameOneName(ldb, mem_ctx, 0,
				  format_offered, 
				  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
				  name,
				  &info1);
	if (!W_ERROR_IS_OK(werr)) {
		return werror_to_ntstatus(werr);
	}
	switch (info1.status) {
	case DRSUAPI_DS_NAME_STATUS_OK:
		break;
	case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
	case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
	case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
		return NT_STATUS_NO_SUCH_USER;
	case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
	default:
		return NT_STATUS_UNSUCCESSFUL;
	}

	*nt4_domain = talloc_strdup(mem_ctx, info1.result_name);
	if (*nt4_domain == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	p = strchr(*nt4_domain, '\\');
	if (!p) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	p[0] = '\0';

	*nt4_account = talloc_strdup(mem_ctx, &p[1]);
	if (*nt4_account == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	return NT_STATUS_OK;
}