s3-group-mapping: Remove fstrings from GROUP_MAP.
[samba.git] / source3 / rpc_server / lsa / srv_lsa_nt.c
index 2342a0e8aa36d43613b64f89c84c621401f0d7a5..c78f23815c6cf9cd48a5e5b217e302514197502a 100644 (file)
@@ -46,6 +46,9 @@
 #include "auth.h"
 #include "lib/privileges.h"
 #include "rpc_server/srv_access_check.h"
+#include "../librpc/gen_ndr/ndr_wkssvc.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "rpc_client/util_lsarpc.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -55,7 +58,8 @@
 enum lsa_handle_type {
        LSA_HANDLE_POLICY_TYPE = 1,
        LSA_HANDLE_ACCOUNT_TYPE = 2,
-       LSA_HANDLE_TRUST_TYPE = 3};
+       LSA_HANDLE_TRUST_TYPE = 3,
+       LSA_HANDLE_SECRET_TYPE = 4};
 
 struct lsa_info {
        struct dom_sid sid;
@@ -434,7 +438,7 @@ NTSTATUS _lsa_OpenPolicy2(struct pipes_struct *p,
 
        /* Work out max allowed. */
        map_max_allowed_access(p->session_info->security_token,
-                              &p->session_info->utok,
+                              p->session_info->unix_token,
                               &des_access);
 
        /* map the generic bits to the lsa policy ones */
@@ -1478,11 +1482,67 @@ static NTSTATUS lsa_lookup_trusted_domain_by_name(TALLOC_CTX *mem_ctx,
 }
 
 /***************************************************************************
+ _lsa_OpenSecret
  ***************************************************************************/
 
-NTSTATUS _lsa_OpenSecret(struct pipes_struct *p, struct lsa_OpenSecret *r)
+NTSTATUS _lsa_OpenSecret(struct pipes_struct *p,
+                        struct lsa_OpenSecret *r)
 {
-       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       struct lsa_info *handle;
+       struct security_descriptor *psd;
+       NTSTATUS status;
+       uint32_t acc_granted;
+
+       if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (handle->type != LSA_HANDLE_POLICY_TYPE) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (!r->in.name.string) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* Work out max allowed. */
+       map_max_allowed_access(p->session_info->security_token,
+                              p->session_info->unix_token,
+                              &r->in.access_mask);
+
+       /* map the generic bits to the lsa policy ones */
+       se_map_generic(&r->in.access_mask, &lsa_secret_mapping);
+
+       status = pdb_get_secret(p->mem_ctx, r->in.name.string,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                               &psd);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = access_check_object(psd, p->session_info->security_token,
+                                    SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
+                                    r->in.access_mask,
+                                    &acc_granted, "_lsa_OpenSecret");
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = create_lsa_policy_handle(p->mem_ctx, p,
+                                         LSA_HANDLE_SECRET_TYPE,
+                                         acc_granted,
+                                         NULL,
+                                         r->in.name.string,
+                                         psd,
+                                         r->out.sec_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
@@ -1504,11 +1564,11 @@ static NTSTATUS _lsa_OpenTrustedDomain_base(struct pipes_struct *p,
 
        /* Work out max allowed. */
        map_max_allowed_access(p->session_info->security_token,
-                              &p->session_info->utok,
+                              p->session_info->unix_token,
                               &access_mask);
 
        /* map the generic bits to the lsa account ones */
-       se_map_generic(&access_mask, &lsa_account_mapping);
+       se_map_generic(&access_mask, &lsa_trusted_domain_mapping);
 
        /* get the generic lsa account SD until we store it */
        status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
@@ -1701,14 +1761,14 @@ NTSTATUS _lsa_CreateTrustedDomainEx2(struct pipes_struct *p,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (p->session_info->utok.uid != sec_initial_uid() &&
+       if (p->session_info->unix_token->uid != sec_initial_uid() &&
            !nt_token_check_domain_rid(p->session_info->security_token, DOMAIN_RID_ADMINS)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
        /* Work out max allowed. */
        map_max_allowed_access(p->session_info->security_token,
-                              &p->session_info->utok,
+                              p->session_info->unix_token,
                               &r->in.access_mask);
 
        /* map the generic bits to the lsa policy ones */
@@ -1803,7 +1863,7 @@ NTSTATUS _lsa_CreateTrustedDomainEx2(struct pipes_struct *p,
                                          psd,
                                          r->out.trustdom_handle);
        if (!NT_STATUS_IS_OK(status)) {
-               pdb_del_trusteddom_pw(r->in.info->netbios_name.string);
+               pdb_del_trusted_domain(r->in.info->netbios_name.string);
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
@@ -1938,6 +1998,32 @@ NTSTATUS _lsa_CloseTrustedDomainEx(struct pipes_struct *p,
  _lsa_QueryTrustedDomainInfo
  ***************************************************************************/
 
+static NTSTATUS pdb_trusted_domain_2_info_ex(TALLOC_CTX *mem_ctx,
+                                     struct pdb_trusted_domain *td,
+                                     struct lsa_TrustDomainInfoInfoEx *info_ex)
+{
+       if (td->domain_name == NULL ||
+           td->netbios_name == NULL ||
+            is_null_sid(&td->security_identifier)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       info_ex->domain_name.string = talloc_strdup(mem_ctx, td->domain_name);
+       info_ex->netbios_name.string = talloc_strdup(mem_ctx, td->netbios_name);
+       info_ex->sid = dom_sid_dup(mem_ctx, &td->security_identifier);
+       if (info_ex->domain_name.string == NULL ||
+           info_ex->netbios_name.string == NULL ||
+            info_ex->sid == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       info_ex->trust_direction = td->trust_direction;
+       info_ex->trust_type = td->trust_type;
+       info_ex->trust_attributes = td->trust_attributes;
+
+       return NT_STATUS_OK;
+}
+
 NTSTATUS _lsa_QueryTrustedDomainInfo(struct pipes_struct *p,
                                     struct lsa_QueryTrustedDomainInfo *r)
 {
@@ -2027,25 +2113,34 @@ NTSTATUS _lsa_QueryTrustedDomainInfo(struct pipes_struct *p,
        case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
                return NT_STATUS_INVALID_PARAMETER;
        case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
+               info->posix_offset.posix_offset = *td->trust_posix_offset;
                break;
        case LSA_TRUSTED_DOMAIN_INFO_PASSWORD:
                return NT_STATUS_INVALID_INFO_CLASS;
        case LSA_TRUSTED_DOMAIN_INFO_BASIC:
                return NT_STATUS_INVALID_PARAMETER;
        case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
-               init_lsa_StringLarge(&info->info_ex.domain_name, td->domain_name);
-               init_lsa_StringLarge(&info->info_ex.netbios_name, td->netbios_name);
-               info->info_ex.sid = dom_sid_dup(info, &td->security_identifier);
-               if (!info->info_ex.sid) {
-                       return NT_STATUS_NO_MEMORY;
+               status = pdb_trusted_domain_2_info_ex(info, td, &info->info_ex);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
                }
-               info->info_ex.trust_direction = td->trust_direction;
-               info->info_ex.trust_type = td->trust_type;
-               info->info_ex.trust_attributes = td->trust_attributes;
                break;
        case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
                return NT_STATUS_INVALID_INFO_CLASS;
        case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
+               status = pdb_trusted_domain_2_info_ex(info, td,
+                                                     &info->full_info.info_ex);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               info->full_info.posix_offset.posix_offset = *td->trust_posix_offset;
+               status = auth_blob_2_auth_info(p->mem_ctx,
+                                                   td->trust_auth_incoming,
+                                                   td->trust_auth_outgoing,
+                                                   &info->full_info.auth_info);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                break;
        case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
                return NT_STATUS_INVALID_INFO_CLASS;
@@ -2054,8 +2149,17 @@ NTSTATUS _lsa_QueryTrustedDomainInfo(struct pipes_struct *p,
        case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
                return NT_STATUS_INVALID_PARAMETER;
        case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
+               info->full_info2_internal.posix_offset.posix_offset = *td->trust_posix_offset;
+               status = auth_blob_2_auth_info(p->mem_ctx,
+                                         td->trust_auth_incoming,
+                                         td->trust_auth_outgoing,
+                                         &info->full_info2_internal.auth_info);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
                break;
        case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
+               info->enc_types.enc_types = *td->supported_enc_type;
                break;
        default:
                return NT_STATUS_INVALID_PARAMETER;
@@ -2146,19 +2250,243 @@ NTSTATUS _lsa_QueryTrustedDomainInfoByName(struct pipes_struct *p,
 }
 
 /***************************************************************************
+ _lsa_CreateSecret
+ ***************************************************************************/
+
+NTSTATUS _lsa_CreateSecret(struct pipes_struct *p,
+                          struct lsa_CreateSecret *r)
+{
+       NTSTATUS status;
+       struct lsa_info *handle;
+       uint32_t acc_granted;
+       struct security_descriptor *psd;
+       size_t sd_size;
+
+       /* find the connection policy handle. */
+       if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (handle->type != LSA_HANDLE_POLICY_TYPE) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* check if the user has enough rights */
+
+       if (!(handle->access & LSA_POLICY_CREATE_SECRET)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* Work out max allowed. */
+       map_max_allowed_access(p->session_info->security_token,
+                              p->session_info->unix_token,
+                              &r->in.access_mask);
+
+       /* map the generic bits to the lsa policy ones */
+       se_map_generic(&r->in.access_mask, &lsa_secret_mapping);
+
+       status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
+                                   &lsa_secret_mapping,
+                                   NULL, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = access_check_object(psd, p->session_info->security_token,
+                                    SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
+                                    r->in.access_mask,
+                                    &acc_granted, "_lsa_CreateSecret");
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!r->in.name.string) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (strlen(r->in.name.string) > 128) {
+               return NT_STATUS_NAME_TOO_LONG;
+       }
+
+       status = pdb_get_secret(p->mem_ctx, r->in.name.string,
+                               NULL, NULL, NULL, NULL, NULL);
+       if (NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
+       status = pdb_set_secret(r->in.name.string, NULL, NULL, psd);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = create_lsa_policy_handle(p->mem_ctx, p,
+                                         LSA_HANDLE_SECRET_TYPE,
+                                         acc_granted,
+                                         NULL,
+                                         r->in.name.string,
+                                         psd,
+                                         r->out.sec_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ _lsa_SetSecret
  ***************************************************************************/
 
-NTSTATUS _lsa_CreateSecret(struct pipes_struct *p, struct lsa_CreateSecret *r)
+NTSTATUS _lsa_SetSecret(struct pipes_struct *p,
+                       struct lsa_SetSecret *r)
 {
-       return NT_STATUS_ACCESS_DENIED;
+       NTSTATUS status;
+       struct lsa_info *info = NULL;
+       DATA_BLOB blob_new, blob_old;
+       DATA_BLOB cleartext_blob_new = data_blob_null;
+       DATA_BLOB cleartext_blob_old = data_blob_null;
+       DATA_BLOB *cleartext_blob_new_p = NULL;
+       DATA_BLOB *cleartext_blob_old_p = NULL;
+
+       if (!find_policy_by_hnd(p, r->in.sec_handle, (void **)(void *)&info)) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (info->type != LSA_HANDLE_SECRET_TYPE) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (!(info->access & LSA_SECRET_SET_VALUE)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (r->in.new_val) {
+               blob_new = data_blob_const(r->in.new_val->data,
+                                          r->in.new_val->length);
+
+               status = sess_decrypt_blob(p->mem_ctx, &blob_new,
+                                          &p->session_info->session_key,
+                                          &cleartext_blob_new);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               cleartext_blob_new_p = &cleartext_blob_new;
+       }
+
+       if (r->in.old_val) {
+               blob_old = data_blob_const(r->in.old_val->data,
+                                          r->in.old_val->length);
+
+               status = sess_decrypt_blob(p->mem_ctx, &blob_old,
+                                          &p->session_info->session_key,
+                                          &cleartext_blob_old);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               cleartext_blob_old_p = &cleartext_blob_old;
+       }
+
+       status = pdb_set_secret(info->name, cleartext_blob_new_p, cleartext_blob_old_p, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(10,("_lsa_SetSecret: successfully set new secret\n"));
+       dump_data(10, cleartext_blob_new.data, cleartext_blob_new.length);
+       DEBUG(10,("_lsa_SetSecret: successfully set old secret\n"));
+       dump_data(10, cleartext_blob_old.data, cleartext_blob_old.length);
+#endif
+
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
+ _lsa_QuerySecret
  ***************************************************************************/
 
-NTSTATUS _lsa_SetSecret(struct pipes_struct *p, struct lsa_SetSecret *r)
+NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
+                         struct lsa_QuerySecret *r)
 {
-       return NT_STATUS_ACCESS_DENIED;
+       struct lsa_info *info = NULL;
+       DATA_BLOB blob_new, blob_old;
+       DATA_BLOB blob_new_crypt, blob_old_crypt;
+       NTTIME nttime_new, nttime_old;
+       NTSTATUS status;
+
+       if (!find_policy_by_hnd(p, r->in.sec_handle, (void **)(void *)&info)) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (info->type != LSA_HANDLE_SECRET_TYPE) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (!(info->access & LSA_SECRET_QUERY_VALUE)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       status = pdb_get_secret(p->mem_ctx, info->name,
+                               &blob_new, &nttime_new,
+                               &blob_old, &nttime_old,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (r->in.new_val) {
+               if (blob_new.length) {
+                       if (!r->out.new_val->buf) {
+                               r->out.new_val->buf = talloc_zero(p->mem_ctx, struct lsa_DATA_BUF);
+                       }
+                       if (!r->out.new_val->buf) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+
+                       blob_new_crypt = sess_encrypt_blob(p->mem_ctx, &blob_new,
+                                                          &p->session_info->session_key);
+                       if (!blob_new_crypt.length) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+
+                       r->out.new_val->buf->data       = blob_new_crypt.data;
+                       r->out.new_val->buf->length     = blob_new_crypt.length;
+                       r->out.new_val->buf->size       = blob_new_crypt.length;
+               }
+       }
+
+       if (r->in.old_val) {
+               if (blob_old.length) {
+                       if (!r->out.old_val->buf) {
+                               r->out.old_val->buf = talloc_zero(p->mem_ctx, struct lsa_DATA_BUF);
+                       }
+                       if (!r->out.old_val->buf) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+
+                       blob_old_crypt = sess_encrypt_blob(p->mem_ctx, &blob_old,
+                                                          &p->session_info->session_key);
+                       if (!blob_old_crypt.length) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+
+                       r->out.old_val->buf->data       = blob_old_crypt.data;
+                       r->out.old_val->buf->length     = blob_old_crypt.length;
+                       r->out.old_val->buf->size       = blob_old_crypt.length;
+               }
+       }
+
+       if (r->out.new_mtime) {
+               *r->out.new_mtime = nttime_new;
+       }
+
+       if (r->out.old_mtime) {
+               *r->out.old_mtime = nttime_old;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
@@ -2188,6 +2516,18 @@ NTSTATUS _lsa_DeleteObject(struct pipes_struct *p,
                        return status;
                }
                break;
+       case LSA_HANDLE_TRUST_TYPE:
+               if (!pdb_del_trusteddom_pw(info->name)) {
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
+               status = NT_STATUS_OK;
+               break;
+       case LSA_HANDLE_SECRET_TYPE:
+               status = pdb_delete_secret(info->name);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                       return NT_STATUS_INVALID_HANDLE;
+               }
+               break;
        default:
                return NT_STATUS_INVALID_HANDLE;
        }
@@ -2400,7 +2740,7 @@ NTSTATUS _lsa_GetUserName(struct pipes_struct *p,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (p->session_info->guest) {
+       if (security_session_user_level(p->session_info, NULL) < SECURITY_USER) {
                /*
                 * I'm 99% sure this is not the right place to do this,
                 * global_sid_Anonymous should probably be put into the token
@@ -2411,8 +2751,8 @@ NTSTATUS _lsa_GetUserName(struct pipes_struct *p,
                        return NT_STATUS_NO_MEMORY;
                }
        } else {
-               username = p->session_info->sanitized_username;
-               domname = p->session_info->info3->base.domain.string;
+               username = p->session_info->unix_info->sanitized_username;
+               domname = p->session_info->info->domain_name;
        }
 
        account_name = talloc(p->mem_ctx, struct lsa_String);
@@ -2466,7 +2806,7 @@ NTSTATUS _lsa_CreateAccount(struct pipes_struct *p,
 
        /* Work out max allowed. */
        map_max_allowed_access(p->session_info->security_token,
-                              &p->session_info->utok,
+                              p->session_info->unix_token,
                               &r->in.access_mask);
 
        /* map the generic bits to the lsa policy ones */
@@ -2530,7 +2870,7 @@ NTSTATUS _lsa_OpenAccount(struct pipes_struct *p,
 
        /* Work out max allowed. */
        map_max_allowed_access(p->session_info->security_token,
-                              &p->session_info->utok,
+                              p->session_info->unix_token,
                               &des_access);
 
        /* map the generic bits to the lsa account ones */
@@ -2683,7 +3023,8 @@ NTSTATUS _lsa_SetSystemAccessAccount(struct pipes_struct *p,
                                     struct lsa_SetSystemAccessAccount *r)
 {
        struct lsa_info *info=NULL;
-       GROUP_MAP map;
+       NTSTATUS status;
+       GROUP_MAP *map;
 
        /* find the connection policy handle. */
        if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
@@ -2697,10 +3038,19 @@ NTSTATUS _lsa_SetSystemAccessAccount(struct pipes_struct *p,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (!pdb_getgrsid(&map, info->sid))
+       map = talloc_zero(p->mem_ctx, GROUP_MAP);
+       if (!map) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!pdb_getgrsid(map, info->sid)) {
+               TALLOC_FREE(map);
                return NT_STATUS_NO_SUCH_GROUP;
+       }
 
-       return pdb_update_group_mapping_entry(&map);
+       status = pdb_update_group_mapping_entry(map);
+       TALLOC_FREE(map);
+       return status;
 }
 
 /***************************************************************************
@@ -2840,6 +3190,7 @@ NTSTATUS _lsa_QuerySecurity(struct pipes_struct *p,
        case LSA_HANDLE_POLICY_TYPE:
        case LSA_HANDLE_ACCOUNT_TYPE:
        case LSA_HANDLE_TRUST_TYPE:
+       case LSA_HANDLE_SECRET_TYPE:
                psd = handle->sd;
                sd_size = ndr_size_security_descriptor(psd, 0);
                status = NT_STATUS_OK;
@@ -3195,6 +3546,309 @@ NTSTATUS _lsa_Delete(struct pipes_struct *p,
        return NT_STATUS_NOT_SUPPORTED;
 }
 
+static NTSTATUS info_ex_2_pdb_trusted_domain(
+                                     struct lsa_TrustDomainInfoInfoEx *info_ex,
+                                     struct pdb_trusted_domain *td)
+{
+       if (info_ex->domain_name.string == NULL ||
+           info_ex->netbios_name.string == NULL ||
+            info_ex->sid == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       td->domain_name = talloc_strdup(td, info_ex->domain_name.string);
+       td->netbios_name = talloc_strdup(td, info_ex->netbios_name.string);
+       sid_copy(&td->security_identifier, info_ex->sid);
+       if (td->domain_name == NULL ||
+           td->netbios_name == NULL ||
+            is_null_sid(&td->security_identifier)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       td->trust_direction = info_ex->trust_direction;
+       td->trust_type = info_ex->trust_type;
+       td->trust_attributes = info_ex->trust_attributes;
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS get_trustdom_auth_blob(struct pipes_struct *p,
+                                      TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
+                                      struct trustDomainPasswords *auth_struct)
+{
+       enum ndr_err_code ndr_err;
+
+       arcfour_crypt_blob(auth_blob->data, auth_blob->length,
+                          &p->session_info->session_key);
+       ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
+                                      auth_struct,
+                                      (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS get_trustauth_inout_blob(TALLOC_CTX *mem_ctx,
+                                        struct trustAuthInOutBlob *iopw,
+                                        DATA_BLOB *trustauth_blob)
+{
+       enum ndr_err_code ndr_err;
+
+       ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
+                                      iopw,
+                                      (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS setInfoTrustedDomain_base(struct pipes_struct *p,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct lsa_info *policy,
+                                         enum lsa_TrustDomInfoEnum level,
+                                         union lsa_TrustedDomainInfo *info)
+{
+       struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
+       DATA_BLOB auth_blob;
+       struct trustDomainPasswords auth_struct;
+       NTSTATUS nt_status;
+
+       struct pdb_trusted_domain *td;
+       struct pdb_trusted_domain *orig_td;
+
+       td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
+       if (td == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       switch (level) {
+       case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
+               if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               td->trust_posix_offset = &info->posix_offset.posix_offset;
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
+               if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               nt_status = info_ex_2_pdb_trusted_domain(&info->info_ex, td);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
+               if (!(policy->access & LSA_TRUSTED_SET_AUTH)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               nt_status = auth_info_2_auth_blob(td, &info->auth_info,
+                                                 &td->trust_auth_incoming,
+                                                 &td->trust_auth_outgoing);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
+               if (!(policy->access & (LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_SET_POSIX))) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               td->trust_posix_offset = &info->full_info.posix_offset.posix_offset;
+               nt_status = info_ex_2_pdb_trusted_domain(&info->full_info.info_ex,
+                                                        td);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+               nt_status = auth_info_2_auth_blob(td,
+                                                 &info->full_info.auth_info,
+                                                 &td->trust_auth_incoming,
+                                                 &td->trust_auth_outgoing);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
+               if (!(policy->access & LSA_TRUSTED_SET_AUTH)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               auth_info_int = &info->auth_info_internal;
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
+               if (!(policy->access & (LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_SET_POSIX))) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               td->trust_posix_offset = &info->full_info_internal.posix_offset.posix_offset;
+               nt_status = info_ex_2_pdb_trusted_domain(&info->full_info_internal.info_ex,
+                                                        td);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+               auth_info_int = &info->full_info_internal.auth_info;
+               break;
+       case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
+               if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               td->supported_enc_type = &info->enc_types.enc_types;
+               break;
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* decode auth_info_int if set */
+       if (auth_info_int) {
+
+               /* now decrypt blob */
+               auth_blob = data_blob_const(auth_info_int->auth_blob.data,
+                                           auth_info_int->auth_blob.size);
+
+               nt_status = get_trustdom_auth_blob(p, mem_ctx,
+                                                  &auth_blob, &auth_struct);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+       } else {
+           memset(&auth_struct, 0, sizeof(auth_struct));
+       }
+
+/* TODO: verify only one object matches the dns/netbios/sid triplet and that
+ * this is the one we already have */
+
+/* TODO: check if the trust direction is changed and we need to add or remove
+ * auth data */
+
+/* TODO: check if trust type shall be changed and return an error in this case
+ * */
+       nt_status = pdb_get_trusted_domain_by_sid(p->mem_ctx, &policy->sid,
+                                              &orig_td);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+
+       /* TODO: should we fetch previous values from the existing entry
+        * and append them ? */
+       if (auth_struct.incoming.count) {
+               nt_status = get_trustauth_inout_blob(mem_ctx,
+                                                    &auth_struct.incoming,
+                                                    &td->trust_auth_incoming);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+       } else {
+               ZERO_STRUCT(td->trust_auth_incoming);
+       }
+
+       if (auth_struct.outgoing.count) {
+               nt_status = get_trustauth_inout_blob(mem_ctx,
+                                                    &auth_struct.outgoing,
+                                                    &td->trust_auth_outgoing);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+       } else {
+               ZERO_STRUCT(td->trust_auth_outgoing);
+       }
+
+       nt_status = pdb_set_trusted_domain(orig_td->domain_name, td);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS _lsa_SetTrustedDomainInfo(struct pipes_struct *p,
+                                  struct lsa_SetTrustedDomainInfo *r)
+{
+       NTSTATUS status;
+       struct policy_handle trustdom_handle;
+       struct lsa_OpenTrustedDomain o;
+       struct lsa_SetInformationTrustedDomain s;
+       struct lsa_Close c;
+
+       o.in.handle             = r->in.handle;
+       o.in.sid                = r->in.dom_sid;
+       o.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
+       o.out.trustdom_handle   = &trustdom_handle;
+
+       status = _lsa_OpenTrustedDomain(p, &o);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       s.in.trustdom_handle    = &trustdom_handle;
+       s.in.level              = r->in.level;
+       s.in.info               = r->in.info;
+
+       status = _lsa_SetInformationTrustedDomain(p, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       c.in.handle             = &trustdom_handle;
+       c.out.handle            = &trustdom_handle;
+
+       return _lsa_Close(p, &c);
+}
+
+NTSTATUS _lsa_SetTrustedDomainInfoByName(struct pipes_struct *p,
+                                        struct lsa_SetTrustedDomainInfoByName *r)
+{
+       NTSTATUS status;
+       struct policy_handle trustdom_handle;
+       struct lsa_OpenTrustedDomainByName o;
+       struct lsa_SetInformationTrustedDomain s;
+       struct lsa_Close c;
+
+       o.in.handle             = r->in.handle;
+       o.in.name.string        = r->in.trusted_domain->string;
+       o.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
+       o.out.trustdom_handle   = &trustdom_handle;
+
+       status = _lsa_OpenTrustedDomainByName(p, &o);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
+               return status;
+       }
+
+       s.in.trustdom_handle    = &trustdom_handle;
+       s.in.level              = r->in.level;
+       s.in.info               = r->in.info;
+
+       status = _lsa_SetInformationTrustedDomain(p, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       c.in.handle             = &trustdom_handle;
+       c.out.handle            = &trustdom_handle;
+
+       return _lsa_Close(p, &c);
+}
+
+NTSTATUS _lsa_SetInformationTrustedDomain(struct pipes_struct *p,
+                                         struct lsa_SetInformationTrustedDomain *r)
+{
+       struct lsa_info *policy;
+
+       if (!find_policy_by_hnd(p, r->in.trustdom_handle, (void **)(void *)&policy)) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (policy->type != LSA_HANDLE_TRUST_TYPE) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       return setInfoTrustedDomain_base(p, p->mem_ctx, policy,
+                                        r->in.level, r->in.info);
+}
+
+
 /*
  * From here on the server routines are just dummy ones to make smbd link with
  * librpc/gen_ndr/srv_lsa.c. These routines are actually never called, we are
@@ -3240,26 +3894,6 @@ NTSTATUS _lsa_SetQuotasForAccount(struct pipes_struct *p,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS _lsa_SetInformationTrustedDomain(struct pipes_struct *p,
-                                         struct lsa_SetInformationTrustedDomain *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS _lsa_QuerySecret(struct pipes_struct *p, struct lsa_QuerySecret *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS _lsa_SetTrustedDomainInfo(struct pipes_struct *p,
-                                  struct lsa_SetTrustedDomainInfo *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS _lsa_StorePrivateData(struct pipes_struct *p,
                               struct lsa_StorePrivateData *r)
 {
@@ -3281,13 +3915,6 @@ NTSTATUS _lsa_SetInfoPolicy2(struct pipes_struct *p,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS _lsa_SetTrustedDomainInfoByName(struct pipes_struct *p,
-                                        struct lsa_SetTrustedDomainInfoByName *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS _lsa_EnumTrustedDomainsEx(struct pipes_struct *p,
                                   struct lsa_EnumTrustedDomainsEx *r)
 {