LCOV - code coverage report
Current view: top level - auth - auth_sam_reply.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 347 465 74.6 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Convert a server info struct into the form for PAC and NETLOGON replies
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2011
       7             :    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "librpc/gen_ndr/auth.h"
      25             : #include "libcli/security/security.h"
      26             : #include "auth/auth_sam_reply.h"
      27             : 
      28             : /* Returns true if this SID belongs in SamBaseInfo, otherwise false. */
      29     1197074 : static bool is_base_sid(const struct auth_SidAttr *sid,
      30             :                         const struct dom_sid *domain_sid)
      31             : {
      32     1197074 :         if (sid->attrs & SE_GROUP_RESOURCE) {
      33             :                 /*
      34             :                  * Resource groups don't belong in the base
      35             :                  * RIDs, they're handled elsewhere.
      36             :                  */
      37      140144 :                 return false;
      38             :         }
      39             : 
      40             :         /*
      41             :          * This SID belongs in the base structure only if it's in the account's
      42             :          * domain.
      43             :          */
      44     1049204 :         return dom_sid_in_domain(domain_sid, &sid->sid);
      45             : }
      46             : 
      47             : /* Stores a SID in a previously allocated array. */
      48      174679 : static NTSTATUS store_extra_sid(struct netr_SidAttr *sids,
      49             :                                 uint32_t *sidcount,
      50             :                                 const uint32_t allocated_sids,
      51             :                                 const struct auth_SidAttr *sid)
      52             : {
      53             :         /* Check we aren't about to overflow our allocation. */
      54      174679 :         if (*sidcount >= allocated_sids) {
      55           0 :                 return NT_STATUS_INVALID_PARAMETER;
      56             :         }
      57             : 
      58      174679 :         sids[*sidcount].sid = dom_sid_dup(sids, &sid->sid);
      59      174679 :         if (sids[*sidcount].sid == NULL) {
      60           0 :                 return NT_STATUS_NO_MEMORY;
      61             :         }
      62      174679 :         sids[*sidcount].attributes = sid->attrs;
      63      174679 :         *sidcount += 1;
      64             : 
      65      174679 :         return NT_STATUS_OK;
      66             : }
      67             : 
      68             : /*
      69             :  * Stores a resource SID in a previously allocated array, either Extra SIDs or
      70             :  * Resource SIDs. Any SID within the domain of the first SID so added is stored
      71             :  * there, while remaining SIDs are stored in Extra SIDs.
      72             :  */
      73       16526 : static NTSTATUS store_resource_sid(struct netr_SidAttr *sids,
      74             :                                    uint32_t *sidcount,
      75             :                                    const uint32_t allocated_sids,
      76             :                                    const struct auth_SidAttr *sid,
      77             :                                    struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups,
      78             :                                    const uint32_t allocated_resource_groups)
      79             : {
      80         581 :         NTSTATUS status;
      81             : 
      82       16526 :         struct dom_sid *resource_domain = NULL;
      83         581 :         uint32_t rid;
      84             : 
      85       16526 :         if (resource_groups == NULL) {
      86           0 :                 return NT_STATUS_INVALID_PARAMETER;
      87             :         }
      88             : 
      89             :         /* Split the SID into domain and RID.  */
      90       16526 :         status = dom_sid_split_rid(resource_groups, &sid->sid, &resource_domain, &rid);
      91       16526 :         if (!NT_STATUS_IS_OK(status)) {
      92           0 :                 return status;
      93             :         }
      94             : 
      95       16526 :         if (resource_groups->domain_sid == NULL) {
      96             :                 /*
      97             :                  * There is no domain SID set. Set it to the domain of this SID.
      98             :                  */
      99       16506 :                 resource_groups->domain_sid = resource_domain;
     100             :         } else {
     101             :                 /*
     102             :                  * A domain SID has already been set. Check whether this SID's
     103             :                  * domain matches.
     104             :                  *
     105             :                  * Assuming that resource SIDs have been obtained with
     106             :                  * dsdb_expand_nested_groups(), they should all be within the
     107             :                  * same domain (ours), so unless something has gone horribly
     108             :                  * wrong, we should always find that they match.
     109             :                  */
     110          20 :                 bool match = dom_sid_equal(resource_groups->domain_sid, resource_domain);
     111          20 :                 talloc_free(resource_domain);
     112          20 :                 if (!match) {
     113             :                         /*
     114             :                          * It doesn't match, so we can't store this SID here. It
     115             :                          * will have to go in Extra SIDs.
     116             :                          */
     117           0 :                         return store_extra_sid(sids, sidcount, allocated_sids, sid);
     118             :                 }
     119             :         }
     120             : 
     121             :         /* Store the SID in Resource SIDs. */
     122             : 
     123             :         /* Check we aren't about to overflow our allocation. */
     124       16526 :         if (resource_groups->groups.count >= allocated_resource_groups) {
     125           0 :                 return NT_STATUS_INVALID_PARAMETER;
     126             :         }
     127             : 
     128       16526 :         resource_groups->groups.rids[resource_groups->groups.count].rid = rid;
     129       16526 :         resource_groups->groups.rids[resource_groups->groups.count].attributes = sid->attrs;
     130       16526 :         resource_groups->groups.count++;
     131             : 
     132       16526 :         return NT_STATUS_OK;
     133             : }
     134             : 
     135             : /*
     136             :  * Stores a SID in a previously allocated array, or excludes it if we are not
     137             :  * storing resource groups. It will be placed in either Extra SIDs or Resource
     138             :  * SIDs, depending on which is appropriate.
     139             :  */
     140      239854 : static NTSTATUS store_sid(struct netr_SidAttr *sids,
     141             :                           uint32_t *sidcount,
     142             :                           const uint32_t allocated_sids,
     143             :                           const struct auth_SidAttr *sid,
     144             :                           struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups,
     145             :                           const uint32_t allocated_resource_groups,
     146             :                           const enum auth_group_inclusion group_inclusion)
     147             : {
     148             :         /* See if it's a resource SID. */
     149      239854 :         if (sid->attrs & SE_GROUP_RESOURCE) {
     150             :                 /*
     151             :                  * If this is the SID of a resource group, determine whether it
     152             :                  * should be included or filtered out.
     153             :                  */
     154       73935 :                 switch (group_inclusion) {
     155        7486 :                 case AUTH_INCLUDE_RESOURCE_GROUPS:
     156             :                         /* Include this SID in Extra SIDs. */
     157        7486 :                         break;
     158       16526 :                 case AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED:
     159             :                         /*
     160             :                          * Try to include this SID in Resource Groups. If this
     161             :                          * can't be arranged, we shall fall back to Extra
     162             :                          * SIDs.
     163             :                          */
     164       63167 :                         return store_resource_sid(sids,
     165             :                                                   sidcount,
     166             :                                                   allocated_sids,
     167             :                                                   sid,
     168             :                                                   resource_groups,
     169             :                                                   allocated_resource_groups);
     170       48649 :                 case AUTH_EXCLUDE_RESOURCE_GROUPS:
     171             :                         /* Ignore this SID. */
     172       48649 :                         return NT_STATUS_OK;
     173           0 :                 default:
     174             :                         /* This means we have a bug. */
     175           0 :                         DBG_ERR("invalid group inclusion parameter: %u\n", group_inclusion);
     176           0 :                         return NT_STATUS_INVALID_PARAMETER;
     177             :                 }
     178             :         }
     179             : 
     180             :         /* Just store the SID in Extra SIDs. */
     181      174679 :         return store_extra_sid(sids,
     182             :                                sidcount,
     183             :                                allocated_sids,
     184             :                                sid);
     185             : }
     186             : 
     187       90646 : static NTSTATUS auth_convert_user_info_dc_sambaseinfo(TALLOC_CTX *mem_ctx,
     188             :                                 const struct auth_user_info_dc *user_info_dc,
     189             :                                 struct netr_SamBaseInfo *sam)
     190             : {
     191        4104 :         NTSTATUS status;
     192        4104 :         const struct auth_user_info *info;
     193             : 
     194       90646 :         ZERO_STRUCTP(sam);
     195             : 
     196       90646 :         if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX) {
     197       90646 :                 status = dom_sid_split_rid(sam, &user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid,
     198             :                                            &sam->domain_sid, &sam->rid);
     199       90646 :                 if (!NT_STATUS_IS_OK(status)) {
     200           0 :                         return status;
     201             :                 }
     202             :         } else {
     203           0 :                 return NT_STATUS_INVALID_PARAMETER;
     204             :         }
     205             : 
     206       90646 :         if (user_info_dc->num_sids > PRIMARY_GROUP_SID_INDEX) {
     207       90645 :                 status = dom_sid_split_rid(NULL, &user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid,
     208             :                                            NULL, &sam->primary_gid);
     209       90645 :                 if (!NT_STATUS_IS_OK(status)) {
     210           0 :                         return status;
     211             :                 }
     212             :         } else {
     213             :                 /* if we have to encode something like SYSTEM (with no
     214             :                  * second SID in the token) then this is the only
     215             :                  * choice */
     216           1 :                 sam->primary_gid = sam->rid;
     217             :         }
     218             : 
     219       90646 :         info = user_info_dc->info;
     220             : 
     221       90646 :         sam->logon_time = info->last_logon;
     222       90646 :         sam->logoff_time =  info->last_logoff;
     223       90646 :         sam->kickoff_time = info->acct_expiry;
     224       90646 :         sam->last_password_change = info->last_password_change;
     225       90646 :         sam->allow_password_change = info->allow_password_change;
     226       90646 :         sam->force_password_change = info->force_password_change;
     227             : 
     228             : #define _COPY_STRING_TALLOC(src_name, dst_name) do { \
     229             :         if (info->src_name != NULL) {\
     230             :                 sam->dst_name.string = talloc_strdup(mem_ctx, info->src_name); \
     231             :                 if (sam->dst_name.string == NULL) { \
     232             :                         return NT_STATUS_NO_MEMORY; \
     233             :                 } \
     234             :         } \
     235             : } while(0)
     236       90646 :         _COPY_STRING_TALLOC(account_name, account_name);
     237       90646 :         _COPY_STRING_TALLOC(full_name, full_name);
     238       90646 :         _COPY_STRING_TALLOC(logon_script, logon_script);
     239       90646 :         _COPY_STRING_TALLOC(profile_path, profile_path);
     240       90646 :         _COPY_STRING_TALLOC(home_directory, home_directory);
     241       90646 :         _COPY_STRING_TALLOC(home_drive, home_drive);
     242       90646 :         _COPY_STRING_TALLOC(logon_server, logon_server);
     243       90646 :         _COPY_STRING_TALLOC(domain_name, logon_domain);
     244             : #undef _COPY_STRING_TALLOC
     245             : 
     246       90646 :         sam->logon_count = info->logon_count;
     247       90646 :         sam->bad_password_count = info->bad_password_count;
     248       90646 :         sam->groups.count = 0;
     249       90646 :         sam->groups.rids = NULL;
     250             : 
     251       90646 :         if (user_info_dc->num_sids > REMAINING_SIDS_INDEX) {
     252        4103 :                 size_t i;
     253       90645 :                 sam->groups.rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
     254             :                                                 user_info_dc->num_sids);
     255             : 
     256       90645 :                 if (sam->groups.rids == NULL)
     257           0 :                         return NT_STATUS_NO_MEMORY;
     258             : 
     259      689182 :                 for (i=REMAINING_SIDS_INDEX; i<user_info_dc->num_sids; i++) {
     260      598537 :                         struct auth_SidAttr *group_sid = &user_info_dc->sids[i];
     261             : 
     262      598537 :                         bool belongs_in_base = is_base_sid(group_sid, sam->domain_sid);
     263      594674 :                         if (!belongs_in_base) {
     264             :                                 /* We handle this elsewhere */
     265      239854 :                                 continue;
     266             :                         }
     267      358683 :                         sam->groups.rids[sam->groups.count].rid =
     268      358683 :                                 group_sid->sid.sub_auths[group_sid->sid.num_auths-1];
     269             : 
     270      358683 :                         sam->groups.rids[sam->groups.count].attributes = group_sid->attrs;
     271      358683 :                         sam->groups.count += 1;
     272             :                 }
     273             : 
     274       90645 :                 if (sam->groups.count == 0) {
     275           0 :                         TALLOC_FREE(sam->groups.rids);
     276             :                 }
     277             :         }
     278             : 
     279       90646 :         sam->user_flags = info->user_flags; /* w2k3 uses NETLOGON_EXTRA_SIDS | NETLOGON_NTLMV2_ENABLED */
     280       90646 :         sam->acct_flags = user_info_dc->info->acct_flags;
     281       90646 :         sam->sub_auth_status = 0;
     282       90646 :         sam->last_successful_logon = 0;
     283       90646 :         sam->last_failed_logon = 0;
     284       90646 :         sam->failed_logon_count = 0;
     285       90646 :         sam->reserved = 0;
     286             : 
     287       90646 :         ZERO_STRUCT(sam->key);
     288       90646 :         if (user_info_dc->user_session_key.length == sizeof(sam->key.key)) {
     289        9957 :                 memcpy(sam->key.key, user_info_dc->user_session_key.data, sizeof(sam->key.key));
     290             :         }
     291             : 
     292       90646 :         ZERO_STRUCT(sam->LMSessKey);
     293       90646 :         if (user_info_dc->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
     294        8682 :                 memcpy(sam->LMSessKey.key, user_info_dc->lm_session_key.data,
     295             :                        sizeof(sam->LMSessKey.key));
     296             :         }
     297             : 
     298       90646 :         return NT_STATUS_OK;
     299             : }
     300             : 
     301             : /* Note that the validity of the _sam6 and resource_groups structures is only as
     302             :  * long as the user_info_dc it was generated from */
     303       90646 : NTSTATUS auth_convert_user_info_dc_saminfo6(TALLOC_CTX *mem_ctx,
     304             :                                             const struct auth_user_info_dc *user_info_dc,
     305             :                                             enum auth_group_inclusion group_inclusion,
     306             :                                             struct netr_SamInfo6 **_sam6,
     307             :                                             struct PAC_DOMAIN_GROUP_MEMBERSHIP **_resource_groups)
     308             : {
     309        4104 :         NTSTATUS status;
     310       90646 :         struct netr_SamInfo6 *sam6 = NULL;
     311       90646 :         struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups = NULL;
     312        4104 :         size_t i;
     313             : 
     314       90646 :         const uint32_t allocated_sids = user_info_dc->num_sids;
     315       90646 :         uint32_t allocated_resource_groups = 0;
     316             : 
     317       90646 :         sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
     318       90646 :         if (sam6 == NULL) {
     319           0 :                 return NT_STATUS_NO_MEMORY;
     320             :         }
     321             : 
     322       90646 :         if (_resource_groups == NULL) {
     323       11041 :                 if (group_inclusion == AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED) {
     324           0 :                         DBG_ERR("_resource_groups parameter not provided to receive resource groups!\n");
     325           0 :                         TALLOC_FREE(sam6);
     326           0 :                         return NT_STATUS_INVALID_PARAMETER;
     327             :                 }
     328       79605 :         } else if (group_inclusion == AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED) {
     329       23794 :                 *_resource_groups = NULL;
     330             : 
     331             :                 /* Allocate resource groups structure. */
     332       23794 :                 resource_groups = talloc_zero(mem_ctx, struct PAC_DOMAIN_GROUP_MEMBERSHIP);
     333       23794 :                 if (resource_groups == NULL) {
     334           0 :                         TALLOC_FREE(sam6);
     335           0 :                         return NT_STATUS_NO_MEMORY;
     336             :                 }
     337             : 
     338             :                 /*
     339             :                  * Allocate enough space to store user_info_dc->num_sids
     340             :                  * RIDs in the worst case.
     341             :                  */
     342       23794 :                 allocated_resource_groups = user_info_dc->num_sids;
     343       23794 :                 resource_groups->groups.rids = talloc_zero_array(resource_groups,
     344             :                                                                  struct samr_RidWithAttribute,
     345             :                                                                  allocated_resource_groups);
     346       23794 :                 if (resource_groups->groups.rids == NULL) {
     347           0 :                         TALLOC_FREE(sam6);
     348           0 :                         TALLOC_FREE(resource_groups);
     349           0 :                         return NT_STATUS_NO_MEMORY;
     350             :                 }
     351             :         } else {
     352             :                 /* No resource groups will be provided. */
     353       55811 :                 *_resource_groups = NULL;
     354             :         }
     355             : 
     356       90646 :         status = auth_convert_user_info_dc_sambaseinfo(sam6,
     357             :                                                        user_info_dc,
     358             :                                                        &sam6->base);
     359       90646 :         if (!NT_STATUS_IS_OK(status)) {
     360           0 :                 TALLOC_FREE(sam6);
     361           0 :                 TALLOC_FREE(resource_groups);
     362           0 :                 return status;
     363             :         }
     364             : 
     365             :         /*
     366             :          * Allocate enough space to store user_info_dc->num_sids SIDs in the
     367             :          * worst case.
     368             :          */
     369       90646 :         sam6->sids = talloc_zero_array(sam6, struct netr_SidAttr,
     370             :                                        allocated_sids);
     371       90646 :         if (sam6->sids == NULL) {
     372           0 :                 TALLOC_FREE(sam6);
     373           0 :                 TALLOC_FREE(resource_groups);
     374           0 :                 return NT_STATUS_NO_MEMORY;
     375             :         }
     376             : 
     377             :         /* We don't put the user and group SIDs in there */
     378      689183 :         for (i=REMAINING_SIDS_INDEX; i<user_info_dc->num_sids; i++) {
     379      598537 :                 struct auth_SidAttr *group_sid = &user_info_dc->sids[i];
     380      598537 :                 bool belongs_in_base = is_base_sid(group_sid, sam6->base.domain_sid);
     381      594674 :                 if (belongs_in_base) {
     382             :                         /* We already handled this in the base. */
     383      358683 :                         continue;
     384             :                 }
     385             : 
     386      239854 :                 status = store_sid(sam6->sids,
     387             :                                    &sam6->sidcount,
     388             :                                    allocated_sids,
     389             :                                    group_sid,
     390             :                                    resource_groups,
     391             :                                    allocated_resource_groups,
     392             :                                    group_inclusion);
     393      239854 :                 if (!NT_STATUS_IS_OK(status)) {
     394           0 :                         TALLOC_FREE(sam6);
     395           0 :                         TALLOC_FREE(resource_groups);
     396           0 :                         return status;
     397             :                 }
     398             :         }
     399       90646 :         if (sam6->sidcount) {
     400       88330 :                 sam6->base.user_flags |= NETLOGON_EXTRA_SIDS;
     401             :         } else {
     402        2316 :                 sam6->base.user_flags &= ~NETLOGON_EXTRA_SIDS;
     403        2316 :                 TALLOC_FREE(sam6->sids);
     404             :         }
     405             : 
     406       90646 :         if (user_info_dc->info->dns_domain_name != NULL) {
     407      177186 :                 sam6->dns_domainname.string = talloc_strdup(sam6,
     408       86542 :                                         user_info_dc->info->dns_domain_name);
     409       90644 :                 if (sam6->dns_domainname.string == NULL) {
     410           0 :                         TALLOC_FREE(sam6);
     411           0 :                         TALLOC_FREE(resource_groups);
     412           0 :                         return NT_STATUS_NO_MEMORY;
     413             :                 }
     414             :         }
     415             : 
     416       90646 :         if (user_info_dc->info->user_principal_name != NULL) {
     417      177186 :                 sam6->principal_name.string = talloc_strdup(sam6,
     418       86542 :                                         user_info_dc->info->user_principal_name);
     419       90644 :                 if (sam6->principal_name.string == NULL) {
     420           0 :                         TALLOC_FREE(sam6);
     421           0 :                         TALLOC_FREE(resource_groups);
     422           0 :                         return NT_STATUS_NO_MEMORY;
     423             :                 }
     424             :         }
     425             : 
     426       90646 :         *_sam6 = sam6;
     427       90646 :         if (resource_groups != NULL) {
     428       23794 :                 if (resource_groups->groups.count > 0) {
     429       16506 :                         *_resource_groups = resource_groups;
     430             :                 } else {
     431        7288 :                         TALLOC_FREE(resource_groups);
     432             :                 }
     433             :         }
     434       90646 :         return NT_STATUS_OK;
     435             : }
     436             : 
     437             : /* Note that the validity of the _sam2 structure is only as long as
     438             :  * the user_info_dc it was generated from */
     439        4254 : NTSTATUS auth_convert_user_info_dc_saminfo2(TALLOC_CTX *mem_ctx,
     440             :                                            const struct auth_user_info_dc *user_info_dc,
     441             :                                            enum auth_group_inclusion group_inclusion,
     442             :                                            struct netr_SamInfo2 **_sam2)
     443             : {
     444         601 :         NTSTATUS status;
     445        4254 :         struct netr_SamInfo6 *sam6 = NULL;
     446        4254 :         struct netr_SamInfo2 *sam2 = NULL;
     447             : 
     448        4254 :         sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
     449        4254 :         if (sam2 == NULL) {
     450           0 :                 return NT_STATUS_NO_MEMORY;
     451             :         }
     452             : 
     453        4254 :         status = auth_convert_user_info_dc_saminfo6(sam2, user_info_dc,
     454             :                                                     group_inclusion, &sam6,
     455             :                                                     NULL);
     456        4254 :         if (!NT_STATUS_IS_OK(status)) {
     457           0 :                 TALLOC_FREE(sam2);
     458           0 :                 return status;
     459             :         }
     460        4254 :         sam2->base   = sam6->base;
     461             :         /*
     462             :          * We have nowhere to put sam6->sids, so we follow Windows here and drop
     463             :          * it. Any resource groups it happened to contain are lost.
     464             :          */
     465        4254 :         sam2->base.user_flags &= ~NETLOGON_EXTRA_SIDS;
     466        4254 :         TALLOC_FREE(sam6->sids);
     467             : 
     468        4254 :         *_sam2 = sam2;
     469        4254 :         return NT_STATUS_OK;
     470             : }
     471             : 
     472             : /* Note that the validity of the _sam3 structure is only as long as
     473             :  * the user_info_dc it was generated from */
     474       83977 : NTSTATUS auth_convert_user_info_dc_saminfo3(TALLOC_CTX *mem_ctx,
     475             :                                            const struct auth_user_info_dc *user_info_dc,
     476             :                                            enum auth_group_inclusion group_inclusion,
     477             :                                            struct netr_SamInfo3 **_sam3,
     478             :                                            struct PAC_DOMAIN_GROUP_MEMBERSHIP **_resource_groups)
     479             : {
     480        3431 :         NTSTATUS status;
     481       83977 :         struct netr_SamInfo6 *sam6 = NULL;
     482       83977 :         struct netr_SamInfo3 *sam3 = NULL;
     483             : 
     484       83977 :         sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
     485       83977 :         if (sam3 == NULL) {
     486           0 :                 return NT_STATUS_NO_MEMORY;
     487             :         }
     488             : 
     489       83977 :         status = auth_convert_user_info_dc_saminfo6(sam3, user_info_dc,
     490             :                                                     group_inclusion, &sam6,
     491             :                                                     _resource_groups);
     492       83977 :         if (!NT_STATUS_IS_OK(status)) {
     493           0 :                 TALLOC_FREE(sam3);
     494           0 :                 return status;
     495             :         }
     496       83977 :         sam3->base   = sam6->base;
     497       83977 :         sam3->sidcount       = sam6->sidcount;
     498       83977 :         sam3->sids   = sam6->sids;
     499             : 
     500       83977 :         *_sam3 = sam3;
     501       83977 :         return NT_STATUS_OK;
     502             : }
     503             : 
     504             : /**
     505             :  * Make a user_info struct from the info3 or similar returned by a domain logon.
     506             :  *
     507             :  * The netr_SamInfo3 is also a key structure in the source3 auth subsystem
     508             :  */
     509             : 
     510      104552 : NTSTATUS make_user_info_SamBaseInfo(TALLOC_CTX *mem_ctx,
     511             :                                     const char *account_name,
     512             :                                     const struct netr_SamBaseInfo *base,
     513             :                                     bool authenticated,
     514             :                                     struct auth_user_info **_user_info)
     515             : {
     516        2543 :         struct auth_user_info *info;
     517             : 
     518      104552 :         info = talloc_zero(mem_ctx, struct auth_user_info);
     519      104552 :         if (info == NULL) {
     520           0 :                 return NT_STATUS_NO_MEMORY;
     521             :         }
     522             : 
     523      104552 :         if (base->account_name.string) {
     524      104552 :                 info->account_name = talloc_strdup(info, base->account_name.string);
     525             :         } else {
     526           0 :                 info->account_name = talloc_strdup(info, account_name);
     527             :         }
     528      104552 :         if (info->account_name == NULL) {
     529           0 :                 talloc_free(info);
     530           0 :                 return NT_STATUS_NO_MEMORY;
     531             :         }
     532             : 
     533      104552 :         if (base->logon_domain.string) {
     534      104552 :                 info->domain_name = talloc_strdup(info, base->logon_domain.string);
     535      104552 :                 if (info->domain_name == NULL) {
     536           0 :                         talloc_free(info);
     537           0 :                         return NT_STATUS_NO_MEMORY;
     538             :                 }
     539             :         }
     540             : 
     541      104552 :         if (base->full_name.string) {
     542      103546 :                 info->full_name = talloc_strdup(info, base->full_name.string);
     543      103546 :                 if (info->full_name == NULL) {
     544           0 :                         talloc_free(info);
     545           0 :                         return NT_STATUS_NO_MEMORY;
     546             :                 }
     547             :         }
     548      104552 :         if (base->logon_script.string) {
     549      103546 :                 info->logon_script = talloc_strdup(info, base->logon_script.string);
     550      103546 :                 if (info->logon_script == NULL) {
     551           0 :                         talloc_free(info);
     552           0 :                         return NT_STATUS_NO_MEMORY;
     553             :                 }
     554             :         }
     555      104552 :         if (base->profile_path.string) {
     556      103546 :                 info->profile_path = talloc_strdup(info, base->profile_path.string);
     557      103546 :                 if (info->profile_path == NULL) {
     558           0 :                         talloc_free(info);
     559           0 :                         return NT_STATUS_NO_MEMORY;
     560             :                 }
     561             :         }
     562      104552 :         if (base->home_directory.string) {
     563      103546 :                 info->home_directory = talloc_strdup(info, base->home_directory.string);
     564      103546 :                 if (info->home_directory == NULL) {
     565           0 :                         talloc_free(info);
     566           0 :                         return NT_STATUS_NO_MEMORY;
     567             :                 }
     568             :         }
     569      104552 :         if (base->home_drive.string) {
     570      103546 :                 info->home_drive = talloc_strdup(info, base->home_drive.string);
     571      103546 :                 if (info->home_drive == NULL) {
     572           0 :                         talloc_free(info);
     573           0 :                         return NT_STATUS_NO_MEMORY;
     574             :                 }
     575             :         }
     576      104552 :         if (base->logon_server.string) {
     577      103546 :                 info->logon_server = talloc_strdup(info, base->logon_server.string);
     578      103546 :                 if (info->logon_server == NULL) {
     579           0 :                         talloc_free(info);
     580           0 :                         return NT_STATUS_NO_MEMORY;
     581             :                 }
     582             :         }
     583      104552 :         info->last_logon = base->logon_time;
     584      104552 :         info->last_logoff = base->logoff_time;
     585      104552 :         info->acct_expiry = base->kickoff_time;
     586      104552 :         info->last_password_change = base->last_password_change;
     587      104552 :         info->allow_password_change = base->allow_password_change;
     588      104552 :         info->force_password_change = base->force_password_change;
     589      104552 :         info->logon_count = base->logon_count;
     590      104552 :         info->bad_password_count = base->bad_password_count;
     591      104552 :         info->acct_flags = base->acct_flags;
     592             : 
     593      104552 :         info->user_flags = base->user_flags;
     594      104552 :         if (!authenticated) {
     595             :                 /*
     596             :                  * We only consider the user authenticated if NETLOGON_GUEST is
     597             :                  * not set, and authenticated is set
     598             :                  */
     599         825 :                 info->user_flags |= NETLOGON_GUEST;
     600             :         }
     601             : 
     602      104552 :         *_user_info = info;
     603      104552 :         return NT_STATUS_OK;
     604             : }
     605             : 
     606        1338 : struct auth_user_info *auth_user_info_copy(TALLOC_CTX *mem_ctx,
     607             :                                            const struct auth_user_info *src)
     608             : {
     609        1338 :         struct auth_user_info *dst = NULL;
     610             : 
     611        1338 :         dst = talloc_zero(mem_ctx, struct auth_user_info);
     612        1338 :         if (dst == NULL) {
     613           0 :                 return NULL;
     614             :         }
     615             : 
     616        1338 :         *dst = *src;
     617             : #define _COPY_STRING(_mem, _str) do { \
     618             :         if ((_str) != NULL) { \
     619             :                 (_str) = talloc_strdup((_mem), (_str)); \
     620             :                 if ((_str) == NULL) { \
     621             :                         TALLOC_FREE(dst); \
     622             :                         return NULL; \
     623             :                 } \
     624             :         } \
     625             : } while(0)
     626        1338 :         _COPY_STRING(dst, dst->account_name);
     627        1338 :         _COPY_STRING(dst, dst->user_principal_name);
     628        1338 :         _COPY_STRING(dst, dst->domain_name);
     629        1338 :         _COPY_STRING(dst, dst->dns_domain_name);
     630        1338 :         _COPY_STRING(dst, dst->full_name);
     631        1338 :         _COPY_STRING(dst, dst->logon_script);
     632        1338 :         _COPY_STRING(dst, dst->profile_path);
     633        1338 :         _COPY_STRING(dst, dst->home_directory);
     634        1338 :         _COPY_STRING(dst, dst->home_drive);
     635        1338 :         _COPY_STRING(dst, dst->logon_server);
     636             : #undef _COPY_STRING
     637             : 
     638        1338 :         return dst;
     639             : }
     640             : 
     641             : /**
     642             :  * Make a user_info_dc struct from the info3 returned by a domain logon
     643             :  */
     644       82631 : NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx,
     645             :                                               const char *account_name,
     646             :                                               uint16_t validation_level,
     647             :                                               const union netr_Validation *validation,
     648             :                                                bool authenticated,
     649             :                                               struct auth_user_info_dc **_user_info_dc)
     650             : {
     651        2543 :         NTSTATUS status;
     652       82631 :         struct auth_user_info_dc *user_info_dc = NULL;
     653       82631 :         const struct netr_SamBaseInfo *base = NULL;
     654       82631 :         uint32_t sidcount = 0;
     655       82631 :         const struct netr_SidAttr *sids = NULL;
     656       82631 :         const char *dns_domainname = NULL;
     657       82631 :         const char *principal = NULL;
     658        2543 :         uint32_t i;
     659             : 
     660       82631 :         switch (validation_level) {
     661           0 :         case 2:
     662           0 :                 if (!validation || !validation->sam2) {
     663           0 :                         return NT_STATUS_INVALID_PARAMETER;
     664             :                 }
     665           0 :                 base = &validation->sam2->base;
     666           0 :                 break;
     667       82343 :         case 3:
     668       82343 :                 if (!validation || !validation->sam3) {
     669           0 :                         return NT_STATUS_INVALID_PARAMETER;
     670             :                 }
     671       82343 :                 base = &validation->sam3->base;
     672       82343 :                 sidcount = validation->sam3->sidcount;
     673       82343 :                 sids = validation->sam3->sids;
     674       82343 :                 break;
     675         288 :         case 6:
     676         288 :                 if (!validation || !validation->sam6) {
     677           0 :                         return NT_STATUS_INVALID_PARAMETER;
     678             :                 }
     679         288 :                 base = &validation->sam6->base;
     680         288 :                 sidcount = validation->sam6->sidcount;
     681         288 :                 sids = validation->sam6->sids;
     682         288 :                 dns_domainname = validation->sam6->dns_domainname.string;
     683         288 :                 principal = validation->sam6->principal_name.string;
     684         288 :                 break;
     685           0 :         default:
     686           0 :                 return NT_STATUS_INVALID_LEVEL;
     687             :         }
     688             : 
     689       82631 :         user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
     690       82631 :         if (user_info_dc == NULL) {
     691           0 :                 return NT_STATUS_NO_MEMORY;
     692             :         }
     693             : 
     694             :         /*
     695             :            Here is where we should check the list of
     696             :            trusted domains, and verify that the SID
     697             :            matches.
     698             :         */
     699       82631 :         if (!base->domain_sid) {
     700           0 :                 DEBUG(0, ("Cannot operate on a Netlogon Validation without a domain SID\n"));
     701           0 :                 talloc_free(user_info_dc);
     702           0 :                 return NT_STATUS_INVALID_PARAMETER;
     703             :         }
     704             : 
     705             :         /* The IDL layer would be a better place to check this, but to
     706             :          * guard the integer addition below, we double-check */
     707       82631 :         if (base->groups.count > 65535) {
     708           0 :                 talloc_free(user_info_dc);
     709           0 :                 return NT_STATUS_INVALID_PARAMETER;
     710             :         }
     711             : 
     712       82631 :         user_info_dc->num_sids = PRIMARY_SIDS_COUNT;
     713             : 
     714       82631 :         user_info_dc->sids = talloc_array(user_info_dc, struct auth_SidAttr,  user_info_dc->num_sids + base->groups.count);
     715       82631 :         if (user_info_dc->sids == NULL) {
     716           0 :                 talloc_free(user_info_dc);
     717           0 :                 return NT_STATUS_NO_MEMORY;
     718             :         }
     719             : 
     720       82631 :         user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid = *base->domain_sid;
     721       82631 :         if (!sid_append_rid(&user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid, base->rid)) {
     722           0 :                 talloc_free(user_info_dc);
     723           0 :                 return NT_STATUS_INVALID_PARAMETER;
     724             :         }
     725       82631 :         user_info_dc->sids[PRIMARY_USER_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
     726             : 
     727       82631 :         user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid = *base->domain_sid;
     728       82631 :         if (!sid_append_rid(&user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid, base->primary_gid)) {
     729           0 :                 talloc_free(user_info_dc);
     730           0 :                 return NT_STATUS_INVALID_PARAMETER;
     731             :         }
     732             :         /*
     733             :          * This attribute value might be wrong if the primary group is a
     734             :          * resource group. But a resource group is not meant to be in a primary
     735             :          * group in the first place, and besides, these attributes will never
     736             :          * make their way into a PAC.
     737             :          */
     738       82631 :         user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
     739             : 
     740      423637 :         for (i = 0; i < base->groups.count; i++) {
     741      341006 :                 user_info_dc->sids[user_info_dc->num_sids].sid = *base->domain_sid;
     742      341006 :                 if (!sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids].sid, base->groups.rids[i].rid)) {
     743           0 :                         talloc_free(user_info_dc);
     744           0 :                         return NT_STATUS_INVALID_PARAMETER;
     745             :                 }
     746      341006 :                 user_info_dc->sids[user_info_dc->num_sids].attrs = base->groups.rids[i].attributes;
     747      341006 :                 user_info_dc->num_sids++;
     748             :         }
     749             : 
     750             :         /* Copy 'other' sids.  We need to do sid filtering here to
     751             :            prevent possible elevation of privileges.  See:
     752             : 
     753             :            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
     754             :          */
     755             : 
     756             :         /*
     757             :          * The IDL layer would be a better place to check this, but to
     758             :          * guard the integer addition below, we double-check
     759             :          */
     760       82631 :         if (sidcount > UINT16_MAX) {
     761           0 :                 talloc_free(user_info_dc);
     762           0 :                 return NT_STATUS_INVALID_PARAMETER;
     763             :         }
     764             : 
     765       82631 :         if (sidcount > 0) {
     766       82554 :                 struct auth_SidAttr *dgrps = user_info_dc->sids;
     767        2541 :                 size_t dgrps_count;
     768             : 
     769       82554 :                 dgrps_count = user_info_dc->num_sids + sidcount;
     770       82554 :                 dgrps = talloc_realloc(user_info_dc, dgrps, struct auth_SidAttr,
     771             :                                        dgrps_count);
     772       82554 :                 if (dgrps == NULL) {
     773           0 :                         talloc_free(user_info_dc);
     774           0 :                         return NT_STATUS_NO_MEMORY;
     775             :                 }
     776             : 
     777      253963 :                 for (i = 0; i < sidcount; i++) {
     778      171409 :                         if (sids[i].sid) {
     779      171409 :                                 dgrps[user_info_dc->num_sids].sid = *sids[i].sid;
     780      171409 :                                 dgrps[user_info_dc->num_sids].attrs = sids[i].attributes;
     781      171409 :                                 user_info_dc->num_sids++;
     782             :                         }
     783             :                 }
     784             : 
     785       82554 :                 user_info_dc->sids = dgrps;
     786             : 
     787             :                 /* Where are the 'global' sids?... */
     788             :         }
     789             : 
     790       82631 :         status = make_user_info_SamBaseInfo(user_info_dc, account_name, base, authenticated, &user_info_dc->info);
     791       82631 :         if (!NT_STATUS_IS_OK(status)) {
     792           0 :                 talloc_free(user_info_dc);
     793           0 :                 return status;
     794             :         }
     795             : 
     796       82631 :         if (dns_domainname != NULL) {
     797         288 :                 user_info_dc->info->dns_domain_name = talloc_strdup(user_info_dc->info,
     798             :                                                                     dns_domainname);
     799         288 :                 if (user_info_dc->info->dns_domain_name == NULL) {
     800           0 :                         talloc_free(user_info_dc);
     801           0 :                         return NT_STATUS_NO_MEMORY;
     802             :                 }
     803             :         }
     804             : 
     805       82631 :         if (principal != NULL) {
     806         288 :                 user_info_dc->info->user_principal_name = talloc_strdup(user_info_dc->info,
     807             :                                                                         principal);
     808         288 :                 if (user_info_dc->info->user_principal_name == NULL) {
     809           0 :                         talloc_free(user_info_dc);
     810           0 :                         return NT_STATUS_NO_MEMORY;
     811             :                 }
     812             :         }
     813             : 
     814             :         /* ensure we are never given NULL session keys */
     815             : 
     816       82631 :         if (all_zero(base->key.key, sizeof(base->key.key))) {
     817       82409 :                 user_info_dc->user_session_key = data_blob(NULL, 0);
     818             :         } else {
     819         222 :                 user_info_dc->user_session_key = data_blob_talloc(user_info_dc, base->key.key, sizeof(base->key.key));
     820         222 :                 if (user_info_dc->user_session_key.data == NULL) {
     821           0 :                         talloc_free(user_info_dc);
     822           0 :                         return NT_STATUS_NO_MEMORY;
     823             :                 }
     824             :         }
     825             : 
     826       82631 :         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
     827       82419 :                 user_info_dc->lm_session_key = data_blob(NULL, 0);
     828             :         } else {
     829         212 :                 user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, base->LMSessKey.key, sizeof(base->LMSessKey.key));
     830         212 :                 if (user_info_dc->lm_session_key.data == NULL) {
     831           0 :                         talloc_free(user_info_dc);
     832           0 :                         return NT_STATUS_NO_MEMORY;
     833             :                 }
     834             :         }
     835             : 
     836       82631 :         *_user_info_dc = user_info_dc;
     837       82631 :         return NT_STATUS_OK;
     838             : }
     839             : 
     840             : /**
     841             :  * Make a user_info_dc struct from the PAC_LOGON_INFO supplied in the krb5
     842             :  * logon. For group_inclusion, pass AUTH_INCLUDE_RESOURCE_GROUPS if SIDs from
     843             :  * the resource groups are to be included in the resulting structure, and pass
     844             :  * AUTH_EXCLUDE_RESOURCE_GROUPS otherwise.
     845             :  */
     846       82257 : NTSTATUS make_user_info_dc_pac(TALLOC_CTX *mem_ctx,
     847             :                               const struct PAC_LOGON_INFO *pac_logon_info,
     848             :                               const struct PAC_UPN_DNS_INFO *pac_upn_dns_info,
     849             :                               const enum auth_group_inclusion group_inclusion,
     850             :                               struct auth_user_info_dc **_user_info_dc)
     851             : {
     852        2541 :         uint32_t i;
     853        2541 :         NTSTATUS nt_status;
     854        2541 :         union netr_Validation validation;
     855        2541 :         struct auth_user_info_dc *user_info_dc;
     856       82257 :         const struct PAC_DOMAIN_GROUP_MEMBERSHIP *rg = NULL;
     857        2541 :         size_t sidcount;
     858             : 
     859       82257 :         validation.sam3 = discard_const_p(struct netr_SamInfo3, &pac_logon_info->info3);
     860             : 
     861       82257 :         nt_status = make_user_info_dc_netlogon_validation(mem_ctx, "", 3, &validation,
     862             :                                                           true, /* This user was authenticated */
     863             :                                                           &user_info_dc);
     864       82257 :         if (!NT_STATUS_IS_OK(nt_status)) {
     865           0 :                 return nt_status;
     866             :         }
     867             : 
     868       82257 :         if (pac_logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS) {
     869       30631 :                 switch (group_inclusion) {
     870       30583 :                 case AUTH_INCLUDE_RESOURCE_GROUPS:
     871             :                         /* Take resource groups from the PAC. */
     872       30583 :                         rg = &pac_logon_info->resource_groups;
     873       30631 :                         break;
     874          48 :                 case AUTH_EXCLUDE_RESOURCE_GROUPS:
     875             :                         /*
     876             :                          * The PAC is from a TGT, or we don't want to process
     877             :                          * its resource groups.
     878             :                          */
     879          48 :                         break;
     880           0 :                 default:
     881           0 :                         DBG_ERR("invalid group inclusion parameter: %u\n", group_inclusion);
     882           0 :                         talloc_free(user_info_dc);
     883           0 :                         return NT_STATUS_INVALID_PARAMETER;
     884             :                 }
     885             :         }
     886             : 
     887       80482 :         if (rg != NULL && rg->groups.count > 0) {
     888             :                 /* The IDL layer would be a better place to check this, but to
     889             :                  * guard the integer addition below, we double-check */
     890       30583 :                 if (rg->groups.count > 65535) {
     891           0 :                         talloc_free(user_info_dc);
     892           0 :                         return NT_STATUS_INVALID_PARAMETER;
     893             :                 }
     894             : 
     895             :                 /*
     896             :                   Here is where we should check the list of
     897             :                   trusted domains, and verify that the SID
     898             :                   matches.
     899             :                 */
     900       30583 :                 if (rg->domain_sid == NULL) {
     901           0 :                         talloc_free(user_info_dc);
     902           0 :                         DEBUG(0, ("Cannot operate on a PAC without a resource domain SID\n"));
     903           0 :                         return NT_STATUS_INVALID_PARAMETER;
     904             :                 }
     905             : 
     906       30583 :                 sidcount = user_info_dc->num_sids + rg->groups.count;
     907       30583 :                 user_info_dc->sids
     908       30583 :                         = talloc_realloc(user_info_dc, user_info_dc->sids, struct auth_SidAttr, sidcount);
     909       30583 :                 if (user_info_dc->sids == NULL) {
     910           0 :                         TALLOC_FREE(user_info_dc);
     911           0 :                         return NT_STATUS_NO_MEMORY;
     912             :                 }
     913             : 
     914       61182 :                 for (i = 0; i < rg->groups.count; i++) {
     915         766 :                         bool ok;
     916             : 
     917       30599 :                         user_info_dc->sids[user_info_dc->num_sids].sid = *rg->domain_sid;
     918       31365 :                         ok = sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids].sid,
     919       30599 :                                             rg->groups.rids[i].rid);
     920       30599 :                         if (!ok) {
     921           0 :                                 talloc_free(user_info_dc);
     922           0 :                                 return NT_STATUS_INVALID_PARAMETER;
     923             :                         }
     924       30599 :                         user_info_dc->sids[user_info_dc->num_sids].attrs = rg->groups.rids[i].attributes;
     925       30599 :                         user_info_dc->num_sids++;
     926             :                 }
     927             :         }
     928             : 
     929       82257 :         if (pac_upn_dns_info != NULL) {
     930       82255 :                 if (pac_upn_dns_info->upn_name != NULL) {
     931      164510 :                         user_info_dc->info->user_principal_name =
     932       82255 :                                 talloc_strdup(user_info_dc->info,
     933       79716 :                                               pac_upn_dns_info->upn_name);
     934       82255 :                         if (user_info_dc->info->user_principal_name == NULL) {
     935           0 :                                 talloc_free(user_info_dc);
     936           0 :                                 return NT_STATUS_NO_MEMORY;
     937             :                         }
     938             :                 }
     939             : 
     940      164510 :                 user_info_dc->info->dns_domain_name =
     941       82255 :                         talloc_strdup(user_info_dc->info,
     942       82255 :                                       pac_upn_dns_info->dns_domain_name);
     943       82255 :                 if (user_info_dc->info->dns_domain_name == NULL) {
     944           0 :                         talloc_free(user_info_dc);
     945           0 :                         return NT_STATUS_NO_MEMORY;
     946             :                 }
     947             : 
     948       82255 :                 if (pac_upn_dns_info->flags & PAC_UPN_DNS_FLAG_CONSTRUCTED) {
     949       78585 :                         user_info_dc->info->user_principal_constructed = true;
     950             :                 }
     951             :         }
     952             : 
     953       82257 :         *_user_info_dc = user_info_dc;
     954       82257 :         return NT_STATUS_OK;
     955             : }

Generated by: LCOV version 1.14