LCOV - code coverage report
Current view: top level - source3/auth - server_info.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 225 358 62.8 %
Date: 2024-02-28 12:06:22 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Authentication utility functions
       4             :    Copyright (C) Volker Lendecke 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "auth.h"
      22             : #include "lib/util_unixsids.h"
      23             : #include "../librpc/gen_ndr/netlogon.h"
      24             : #include "../libcli/security/security.h"
      25             : #include "rpc_client/util_netlogon.h"
      26             : #include "nsswitch/libwbclient/wbclient.h"
      27             : #include "lib/winbind_util.h"
      28             : #include "passdb.h"
      29             : 
      30             : #undef DBGC_CLASS
      31             : #define DBGC_CLASS DBGC_AUTH
      32             : 
      33             : /***************************************************************************
      34             :  Make a server_info struct. Free with TALLOC_FREE().
      35             : ***************************************************************************/
      36             : 
      37       27793 : struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
      38             : {
      39           0 :         struct auth_serversupplied_info *result;
      40             : 
      41       27793 :         result = talloc_zero(mem_ctx, struct auth_serversupplied_info);
      42       27793 :         if (result == NULL) {
      43           0 :                 DEBUG(0, ("talloc failed\n"));
      44           0 :                 return NULL;
      45             :         }
      46             : 
      47             :         /* Initialise the uid and gid values to something non-zero
      48             :            which may save us from giving away root access if there
      49             :            is a bug in allocating these fields. */
      50             : 
      51       27793 :         result->utok.uid = -1;
      52       27793 :         result->utok.gid = -1;
      53             : 
      54       27793 :         return result;
      55             : }
      56             : 
      57             : /****************************************************************************
      58             :  inits a netr_SamInfo2 structure from an auth_serversupplied_info. sam2 must
      59             :  already be initialized and is used as the talloc parent for its members.
      60             : *****************************************************************************/
      61             : 
      62         234 : NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
      63             :                                 struct netr_SamInfo2 *sam2)
      64             : {
      65         234 :         struct netr_SamInfo3 *info3 = NULL;
      66           0 :         NTSTATUS status;
      67             : 
      68         234 :         status = copy_netr_SamInfo3(sam2,
      69         234 :                                     server_info->info3,
      70             :                                     &info3);
      71         234 :         if (!NT_STATUS_IS_OK(status)) {
      72           0 :                 return status;
      73             :         }
      74             : 
      75         234 :         if (server_info->session_key.length) {
      76         234 :                 memcpy(info3->base.key.key,
      77         234 :                        server_info->session_key.data,
      78         234 :                        MIN(sizeof(info3->base.key.key),
      79             :                            server_info->session_key.length));
      80             :         }
      81         234 :         if (server_info->lm_session_key.length) {
      82         226 :                 memcpy(info3->base.LMSessKey.key,
      83         226 :                        server_info->lm_session_key.data,
      84         226 :                        MIN(sizeof(info3->base.LMSessKey.key),
      85             :                            server_info->lm_session_key.length));
      86             :         }
      87             : 
      88         234 :         sam2->base = info3->base;
      89             : 
      90         234 :         return NT_STATUS_OK;
      91             : }
      92             : 
      93             : /****************************************************************************
      94             :  inits a netr_SamInfo3 structure from an auth_serversupplied_info. sam3 must
      95             :  already be initialized and is used as the talloc parent for its members.
      96             : *****************************************************************************/
      97             : 
      98         349 : NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info,
      99             :                                 struct netr_SamInfo3 *sam3)
     100             : {
     101         349 :         struct netr_SamInfo3 *info3 = NULL;
     102           0 :         NTSTATUS status;
     103             : 
     104         349 :         status = copy_netr_SamInfo3(sam3,
     105         349 :                                     server_info->info3,
     106             :                                     &info3);
     107         349 :         if (!NT_STATUS_IS_OK(status)) {
     108           0 :                 return status;
     109             :         }
     110             : 
     111         349 :         if (server_info->session_key.length) {
     112         341 :                 memcpy(info3->base.key.key,
     113         341 :                        server_info->session_key.data,
     114         341 :                        MIN(sizeof(info3->base.key.key),
     115             :                            server_info->session_key.length));
     116             :         }
     117         349 :         if (server_info->lm_session_key.length) {
     118         311 :                 memcpy(info3->base.LMSessKey.key,
     119         311 :                        server_info->lm_session_key.data,
     120         311 :                        MIN(sizeof(info3->base.LMSessKey.key),
     121             :                            server_info->lm_session_key.length));
     122             :         }
     123             : 
     124         349 :         sam3->base = info3->base;
     125             : 
     126         349 :         sam3->sidcount               = 0;
     127         349 :         sam3->sids           = NULL;
     128             : 
     129         349 :         return NT_STATUS_OK;
     130             : }
     131             : 
     132             : /****************************************************************************
     133             :  inits a netr_SamInfo6 structure from an auth_serversupplied_info. sam6 must
     134             :  already be initialized and is used as the talloc parent for its members.
     135             : *****************************************************************************/
     136             : 
     137           0 : NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
     138             :                                 struct netr_SamInfo6 *sam6)
     139             : {
     140           0 :         struct pdb_domain_info *dominfo;
     141           0 :         struct netr_SamInfo3 *info3 = NULL;
     142           0 :         NTSTATUS status;
     143             : 
     144           0 :         if ((pdb_capabilities() & PDB_CAP_ADS) == 0) {
     145           0 :                 DEBUG(10,("Not adding validation info level 6 "
     146             :                            "without ADS passdb backend\n"));
     147           0 :                 return NT_STATUS_INVALID_INFO_CLASS;
     148             :         }
     149             : 
     150           0 :         dominfo = pdb_get_domain_info(sam6);
     151           0 :         if (dominfo == NULL) {
     152           0 :                 return NT_STATUS_NO_MEMORY;
     153             :         }
     154             : 
     155           0 :         status = copy_netr_SamInfo3(sam6,
     156           0 :                                     server_info->info3,
     157             :                                     &info3);
     158           0 :         if (!NT_STATUS_IS_OK(status)) {
     159           0 :                 return status;
     160             :         }
     161             : 
     162           0 :         if (server_info->session_key.length) {
     163           0 :                 memcpy(info3->base.key.key,
     164           0 :                        server_info->session_key.data,
     165           0 :                        MIN(sizeof(info3->base.key.key),
     166             :                            server_info->session_key.length));
     167             :         }
     168           0 :         if (server_info->lm_session_key.length) {
     169           0 :                 memcpy(info3->base.LMSessKey.key,
     170           0 :                        server_info->lm_session_key.data,
     171           0 :                        MIN(sizeof(info3->base.LMSessKey.key),
     172             :                            server_info->lm_session_key.length));
     173             :         }
     174             : 
     175           0 :         sam6->base = info3->base;
     176             : 
     177           0 :         sam6->sidcount               = 0;
     178           0 :         sam6->sids           = NULL;
     179             : 
     180           0 :         sam6->dns_domainname.string = talloc_strdup(sam6, dominfo->dns_domain);
     181           0 :         if (sam6->dns_domainname.string == NULL) {
     182           0 :                 return NT_STATUS_NO_MEMORY;
     183             :         }
     184             : 
     185           0 :         sam6->principal_name.string = talloc_asprintf(
     186             :                 sam6, "%s@%s", sam6->base.account_name.string,
     187             :                 sam6->dns_domainname.string);
     188           0 :         if (sam6->principal_name.string == NULL) {
     189           0 :                 return NT_STATUS_NO_MEMORY;
     190             :         }
     191             : 
     192           0 :         return NT_STATUS_OK;
     193             : }
     194             : 
     195       50355 : static NTSTATUS append_netr_SidAttr(TALLOC_CTX *mem_ctx,
     196             :                                     struct netr_SidAttr **sids,
     197             :                                     uint32_t *count,
     198             :                                     const struct dom_sid2 *asid,
     199             :                                     uint32_t attributes)
     200             : {
     201       50355 :         uint32_t t = *count;
     202             : 
     203       50355 :         *sids = talloc_realloc(mem_ctx, *sids, struct netr_SidAttr, t + 1);
     204       50355 :         if (*sids == NULL) {
     205           0 :                 return NT_STATUS_NO_MEMORY;
     206             :         }
     207       50355 :         (*sids)[t].sid = dom_sid_dup(*sids, asid);
     208       50355 :         if ((*sids)[t].sid == NULL) {
     209           0 :                 return NT_STATUS_NO_MEMORY;
     210             :         }
     211       50355 :         (*sids)[t].attributes = attributes;
     212       50355 :         *count = t + 1;
     213             : 
     214       50355 :         return NT_STATUS_OK;
     215             : }
     216             : 
     217             : /* Fills the samr_RidWithAttributeArray with the provided sids.
     218             :  * If it happens that we have additional groups that do not belong
     219             :  * to the domain, add their sids as extra sids */
     220       25154 : static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
     221             :                                     const struct dom_sid *sids,
     222             :                                     size_t num_sids)
     223             : {
     224       25154 :         uint32_t attributes = SE_GROUP_DEFAULT_FLAGS;
     225           0 :         struct samr_RidWithAttributeArray *groups;
     226           0 :         struct dom_sid *domain_sid;
     227           0 :         unsigned int i;
     228           0 :         NTSTATUS status;
     229           0 :         uint32_t rid;
     230           0 :         bool ok;
     231             : 
     232       25154 :         domain_sid = info3->base.domain_sid;
     233       25154 :         groups = &info3->base.groups;
     234             : 
     235       25154 :         groups->rids = talloc_array(info3,
     236             :                                     struct samr_RidWithAttribute, num_sids);
     237       25154 :         if (!groups->rids) {
     238           0 :                 return NT_STATUS_NO_MEMORY;
     239             :         }
     240             : 
     241       75154 :         for (i = 0; i < num_sids; i++) {
     242       50000 :                 ok = sid_peek_check_rid(domain_sid, &sids[i], &rid);
     243       50000 :                 if (ok) {
     244             :                         /* store domain group rid */
     245         325 :                         groups->rids[groups->count].rid = rid;
     246         325 :                         groups->rids[groups->count].attributes = attributes;
     247         325 :                         groups->count++;
     248         325 :                         continue;
     249             :                 }
     250             : 
     251             :                 /* if this wasn't a domain sid, add it as extra sid */
     252       49675 :                 status = append_netr_SidAttr(info3, &info3->sids,
     253             :                                              &info3->sidcount,
     254       49675 :                                              &sids[i], attributes);
     255       49675 :                 if (!NT_STATUS_IS_OK(status)) {
     256           0 :                         return status;
     257             :                 }
     258             :         }
     259             : 
     260       25154 :         return NT_STATUS_OK;
     261             : }
     262             : 
     263             : /*
     264             :  * Merge resource SIDs, if any, into the passed in info3 structure.
     265             :  */
     266             : 
     267         870 : static NTSTATUS merge_resource_sids(const struct PAC_LOGON_INFO *logon_info,
     268             :                                 struct netr_SamInfo3 *info3)
     269             : {
     270         870 :         uint32_t i = 0;
     271         870 :         const struct PAC_DOMAIN_GROUP_MEMBERSHIP *rg = NULL;
     272             : 
     273         870 :         if (logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS) {
     274         680 :                 rg = &logon_info->resource_groups;
     275             :         }
     276             : 
     277         870 :         if (rg == NULL) {
     278         190 :                 return NT_STATUS_OK;
     279             :         }
     280             : 
     281         680 :         if (rg->domain_sid == NULL) {
     282           0 :                 DEBUG(10, ("Missing Resource Group Domain SID\n"));
     283           0 :                 return NT_STATUS_INVALID_PARAMETER;
     284             :         }
     285             : 
     286             :         /* The IDL layer would be a better place to check this, but to
     287             :          * guard the integer addition below, we double-check */
     288         680 :         if (rg->groups.count > 65535) {
     289           0 :                 DEBUG(10, ("Too much Resource Group RIDs %u\n",
     290             :                           (unsigned)rg->groups.count));
     291           0 :                 return NT_STATUS_INVALID_PARAMETER;
     292             :         }
     293             : 
     294             :         /*
     295             :          * If there are any resource groups (SID Compression) add
     296             :          * them to the extra sids portion of the info3 in the PAC.
     297             :          *
     298             :          * This makes the info3 look like it would if we got the info
     299             :          * from the DC rather than the PAC.
     300             :          */
     301             : 
     302             :         /*
     303             :          * Construct a SID for each RID in the list and then append it
     304             :          * to the info3.
     305             :          */
     306        1360 :         for (i = 0; i < rg->groups.count; i++) {
     307           0 :                 NTSTATUS status;
     308           0 :                 struct dom_sid new_sid;
     309         680 :                 uint32_t attributes = rg->groups.rids[i].attributes;
     310           0 :                 struct dom_sid_buf buf;
     311             : 
     312         680 :                 sid_compose(&new_sid,
     313         680 :                             rg->domain_sid,
     314         680 :                             rg->groups.rids[i].rid);
     315             : 
     316         680 :                 DEBUG(10, ("Adding SID %s to extra SIDS\n",
     317             :                            dom_sid_str_buf(&new_sid, &buf)));
     318             : 
     319         680 :                 status = append_netr_SidAttr(info3, &info3->sids,
     320             :                                         &info3->sidcount,
     321             :                                         &new_sid,
     322             :                                         attributes);
     323         680 :                 if (!NT_STATUS_IS_OK(status)) {
     324           0 :                         DEBUG(1, ("failed to append SID %s to extra SIDS: %s\n",
     325             :                                 dom_sid_str_buf(&new_sid, &buf),
     326             :                                 nt_errstr(status)));
     327           0 :                         return status;
     328             :                 }
     329             :         }
     330             : 
     331         680 :         return NT_STATUS_OK;
     332             : }
     333             : 
     334             : /*
     335             :  * Create a copy of an info3 struct from the struct PAC_LOGON_INFO,
     336             :  * then merge resource SIDs, if any, into it. If successful return
     337             :  * the created info3 struct.
     338             :  */
     339             : 
     340           0 : NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx,
     341             :                                         const struct PAC_LOGON_INFO *logon_info,
     342             :                                         struct netr_SamInfo3 **pp_info3)
     343             : {
     344           0 :         NTSTATUS status;
     345           0 :         struct netr_SamInfo3 *info3 = NULL;
     346             : 
     347           0 :         status = copy_netr_SamInfo3(mem_ctx,
     348             :                                     &logon_info->info3,
     349             :                                     &info3);
     350           0 :         if (!NT_STATUS_IS_OK(status)) {
     351           0 :                 return status;
     352             :         }
     353             : 
     354           0 :         status = merge_resource_sids(logon_info, info3);
     355           0 :         if (!NT_STATUS_IS_OK(status)) {
     356           0 :                 TALLOC_FREE(info3);
     357           0 :                 return status;
     358             :         }
     359           0 :         *pp_info3 = info3;
     360           0 :         return NT_STATUS_OK;
     361             : }
     362             : 
     363             : /*
     364             :  * Create a copy of an info6 struct from the PAC_UPN_DNS_INFO and PAC_LOGON_INFO
     365             :  * then merge resource SIDs, if any, into it. If successful return the created
     366             :  * info6 struct.
     367             :  */
     368         870 : NTSTATUS create_info6_from_pac(TALLOC_CTX *mem_ctx,
     369             :                                const struct PAC_LOGON_INFO *logon_info,
     370             :                                const struct PAC_UPN_DNS_INFO *upn_dns_info,
     371             :                                struct netr_SamInfo6 **pp_info6)
     372             : {
     373           0 :         NTSTATUS status;
     374         870 :         struct netr_SamInfo6 *info6 = NULL;
     375         870 :         struct netr_SamInfo3 *info3 = NULL;
     376             : 
     377         870 :         info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
     378         870 :         if (info6 == NULL) {
     379           0 :                 return NT_STATUS_NO_MEMORY;
     380             :         }
     381             : 
     382         870 :         status = copy_netr_SamInfo3(info6,
     383             :                                     &logon_info->info3,
     384             :                                     &info3);
     385         870 :         if (!NT_STATUS_IS_OK(status)) {
     386           0 :                 TALLOC_FREE(info6);
     387           0 :                 return status;
     388             :         }
     389             : 
     390         870 :         status = merge_resource_sids(logon_info, info3);
     391         870 :         if (!NT_STATUS_IS_OK(status)) {
     392           0 :                 TALLOC_FREE(info6);
     393           0 :                 return status;
     394             :         }
     395             : 
     396         870 :         info6->base = info3->base;
     397         870 :         info6->sids = info3->sids;
     398         870 :         info6->sidcount = info3->sidcount;
     399             : 
     400         870 :         if (upn_dns_info != NULL) {
     401        1492 :                 info6->dns_domainname.string = talloc_strdup(info6,
     402         746 :                                 upn_dns_info->dns_domain_name);
     403         746 :                 if (info6->dns_domainname.string == NULL) {
     404           0 :                         TALLOC_FREE(info6);
     405           0 :                         return NT_STATUS_NO_MEMORY;
     406             :                 }
     407        1492 :                 info6->principal_name.string = talloc_strdup(info6,
     408         746 :                                 upn_dns_info->upn_name);
     409         746 :                 if (info6->principal_name.string == NULL) {
     410           0 :                         TALLOC_FREE(info6);
     411           0 :                         return NT_STATUS_NO_MEMORY;
     412             :                 }
     413             :         }
     414             : 
     415         870 :         *pp_info6 = info6;
     416         870 :         return NT_STATUS_OK;
     417             : }
     418             : 
     419             : /*
     420             :  * Check if this is a "Unix Users" domain user, or a
     421             :  * "Unix Groups" domain group, we need to handle it
     422             :  * in a special way if that's the case.
     423             :  */
     424             : 
     425       25273 : static NTSTATUS SamInfo3_handle_sids(const char *username,
     426             :                         const struct dom_sid *user_sid,
     427             :                         const struct dom_sid *group_sid,
     428             :                         struct netr_SamInfo3 *info3,
     429             :                         struct dom_sid *domain_sid,
     430             :                         struct extra_auth_info *extra)
     431             : {
     432           0 :         struct dom_sid_buf buf;
     433             : 
     434       25273 :         if (sid_check_is_in_unix_users(user_sid)) {
     435             :                 /* in info3 you can only set rids for the user and the
     436             :                  * primary group, and the domain sid must be that of
     437             :                  * the sam domain.
     438             :                  *
     439             :                  * Store a completely bogus value here.
     440             :                  * The real SID is stored in the extra sids.
     441             :                  * Other code will know to look there if (-1) is found
     442             :                  */
     443         112 :                 info3->base.rid = (uint32_t)(-1);
     444         112 :                 sid_copy(&extra->user_sid, user_sid);
     445             : 
     446         112 :                 DEBUG(10, ("Unix User found. Rid marked as "
     447             :                         "special and sid (%s) saved as extra sid\n",
     448             :                         dom_sid_str_buf(user_sid, &buf)));
     449             :         } else {
     450       25161 :                 sid_copy(domain_sid, user_sid);
     451       25161 :                 sid_split_rid(domain_sid, &info3->base.rid);
     452             :         }
     453             : 
     454       25273 :         if (is_null_sid(domain_sid)) {
     455         112 :                 sid_copy(domain_sid, get_global_sam_sid());
     456             :         }
     457             : 
     458             :         /* check if this is a "Unix Groups" domain group,
     459             :          * if so we need special handling */
     460       25273 :         if (sid_check_is_in_unix_groups(group_sid)) {
     461             :                 /* in info3 you can only set rids for the user and the
     462             :                  * primary group, and the domain sid must be that of
     463             :                  * the sam domain.
     464             :                  *
     465             :                  * Store a completely bogus value here.
     466             :                  * The real SID is stored in the extra sids.
     467             :                  * Other code will know to look there if (-1) is found
     468             :                  */
     469           0 :                 info3->base.primary_gid = (uint32_t)(-1);
     470           0 :                 sid_copy(&extra->pgid_sid, group_sid);
     471             : 
     472           0 :                 DEBUG(10, ("Unix Group found. Rid marked as "
     473             :                         "special and sid (%s) saved as extra sid\n",
     474             :                         dom_sid_str_buf(group_sid, &buf)));
     475             :         } else {
     476       25273 :                 bool ok = sid_peek_check_rid(domain_sid, group_sid,
     477             :                                         &info3->base.primary_gid);
     478       25273 :                 if (!ok) {
     479           0 :                         struct dom_sid_buf buf2, buf3;
     480           0 :                         DEBUG(1, ("The primary group domain sid(%s) does not "
     481             :                                 "match the domain sid(%s) for %s(%s)\n",
     482             :                                 dom_sid_str_buf(group_sid, &buf),
     483             :                                 dom_sid_str_buf(domain_sid, &buf2),
     484             :                                 username,
     485             :                                 dom_sid_str_buf(user_sid, &buf3)));
     486           0 :                         return NT_STATUS_INVALID_SID;
     487             :                 }
     488             :         }
     489       25273 :         return NT_STATUS_OK;
     490             : }
     491             : 
     492             : #define RET_NOMEM(ptr) do { \
     493             :         if (!ptr) { \
     494             :                 TALLOC_FREE(info3); \
     495             :                 return NT_STATUS_NO_MEMORY; \
     496             :         } } while(0)
     497             : 
     498       25016 : NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
     499             :                           struct samu *samu,
     500             :                           const char *login_server,
     501             :                           struct netr_SamInfo3 **_info3,
     502             :                           struct extra_auth_info *extra)
     503             : {
     504           0 :         struct netr_SamInfo3 *info3;
     505           0 :         const struct dom_sid *user_sid;
     506           0 :         const struct dom_sid *group_sid;
     507       25016 :         struct dom_sid domain_sid = {0};
     508           0 :         struct dom_sid *group_sids;
     509       25016 :         uint32_t num_group_sids = 0;
     510           0 :         const char *tmp;
     511           0 :         gid_t *gids;
     512           0 :         NTSTATUS status;
     513             : 
     514       25016 :         user_sid = pdb_get_user_sid(samu);
     515       25016 :         group_sid = pdb_get_group_sid(samu);
     516             : 
     517       25016 :         if (!user_sid || !group_sid) {
     518           0 :                 DEBUG(1, ("Sam account is missing sids!\n"));
     519           0 :                 return NT_STATUS_UNSUCCESSFUL;
     520             :         }
     521             : 
     522       25016 :         info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
     523       25016 :         if (!info3) {
     524           0 :                 return NT_STATUS_NO_MEMORY;
     525             :         }
     526             : 
     527       25016 :         status = SamInfo3_handle_sids(pdb_get_username(samu),
     528             :                                 user_sid,
     529             :                                 group_sid,
     530             :                                 info3,
     531             :                                 &domain_sid,
     532             :                                 extra);
     533             : 
     534       25016 :         if (!NT_STATUS_IS_OK(status)) {
     535           0 :                 TALLOC_FREE(info3);
     536           0 :                 return status;
     537             :         }
     538             : 
     539       25016 :         unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
     540       25016 :         unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
     541       25016 :         unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
     542       25016 :         unix_to_nt_time(&info3->base.last_password_change,
     543             :                         pdb_get_pass_last_set_time(samu));
     544       25016 :         unix_to_nt_time(&info3->base.allow_password_change,
     545             :                         pdb_get_pass_can_change_time(samu));
     546       25016 :         unix_to_nt_time(&info3->base.force_password_change,
     547             :                         pdb_get_pass_must_change_time(samu));
     548             : 
     549       25016 :         tmp = pdb_get_username(samu);
     550       25016 :         if (tmp) {
     551       25016 :                 info3->base.account_name.string      = talloc_strdup(info3, tmp);
     552       25016 :                 RET_NOMEM(info3->base.account_name.string);
     553             :         }
     554       25016 :         tmp = pdb_get_fullname(samu);
     555       25016 :         if (tmp) {
     556       25016 :                 info3->base.full_name.string = talloc_strdup(info3, tmp);
     557       25016 :                 RET_NOMEM(info3->base.full_name.string);
     558             :         }
     559       25016 :         tmp = pdb_get_logon_script(samu);
     560       25016 :         if (tmp) {
     561       25016 :                 info3->base.logon_script.string = talloc_strdup(info3, tmp);
     562       25016 :                 RET_NOMEM(info3->base.logon_script.string);
     563             :         }
     564       25016 :         tmp = pdb_get_profile_path(samu);
     565       25016 :         if (tmp) {
     566       25016 :                 info3->base.profile_path.string      = talloc_strdup(info3, tmp);
     567       25016 :                 RET_NOMEM(info3->base.profile_path.string);
     568             :         }
     569       25016 :         tmp = pdb_get_homedir(samu);
     570       25016 :         if (tmp) {
     571       25016 :                 info3->base.home_directory.string = talloc_strdup(info3, tmp);
     572       25016 :                 RET_NOMEM(info3->base.home_directory.string);
     573             :         }
     574       25016 :         tmp = pdb_get_dir_drive(samu);
     575       25016 :         if (tmp) {
     576       25015 :                 info3->base.home_drive.string = talloc_strdup(info3, tmp);
     577       25015 :                 RET_NOMEM(info3->base.home_drive.string);
     578             :         }
     579             : 
     580       25016 :         info3->base.logon_count      = pdb_get_logon_count(samu);
     581       25016 :         info3->base.bad_password_count = pdb_get_bad_password_count(samu);
     582             : 
     583       25016 :         info3->base.logon_domain.string = talloc_strdup(info3,
     584             :                                                   pdb_get_domain(samu));
     585       25016 :         RET_NOMEM(info3->base.logon_domain.string);
     586             : 
     587       25016 :         info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
     588       25016 :         RET_NOMEM(info3->base.domain_sid);
     589             : 
     590       25016 :         status = pdb_enum_group_memberships(mem_ctx, samu,
     591             :                                             &group_sids, &gids,
     592             :                                             &num_group_sids);
     593       25016 :         if (!NT_STATUS_IS_OK(status)) {
     594           0 :                 DEBUG(1, ("Failed to get groups from sam account.\n"));
     595           0 :                 TALLOC_FREE(info3);
     596           0 :                 return status;
     597             :         }
     598             : 
     599       25016 :         if (num_group_sids) {
     600       25016 :                 status = group_sids_to_info3(info3, group_sids, num_group_sids);
     601       25016 :                 if (!NT_STATUS_IS_OK(status)) {
     602           0 :                         TALLOC_FREE(info3);
     603           0 :                         return status;
     604             :                 }
     605             :         }
     606             : 
     607             :         /* We don't need sids and gids after the conversion */
     608       25016 :         TALLOC_FREE(group_sids);
     609       25016 :         TALLOC_FREE(gids);
     610       25016 :         num_group_sids = 0;
     611             : 
     612             :         /* FIXME: should we add other flags ? */
     613       25016 :         info3->base.user_flags = NETLOGON_EXTRA_SIDS;
     614             : 
     615       25016 :         if (login_server) {
     616       25016 :                 info3->base.logon_server.string = talloc_strdup(info3, login_server);
     617       25016 :                 RET_NOMEM(info3->base.logon_server.string);
     618             :         }
     619             : 
     620       25016 :         info3->base.acct_flags = pdb_get_acct_ctrl(samu);
     621             : 
     622       25016 :         *_info3 = info3;
     623       25016 :         return NT_STATUS_OK;
     624             : }
     625             : 
     626         257 : NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
     627             :                             const char *unix_username,
     628             :                             const struct passwd *pwd,
     629             :                             struct netr_SamInfo3 **pinfo3,
     630             :                             struct extra_auth_info *extra)
     631             : {
     632           0 :         struct netr_SamInfo3 *info3;
     633           0 :         NTSTATUS status;
     634           0 :         TALLOC_CTX *tmp_ctx;
     635         257 :         const char *domain_name = NULL;
     636         257 :         const char *user_name = NULL;
     637           0 :         struct dom_sid domain_sid;
     638           0 :         struct dom_sid user_sid;
     639           0 :         struct dom_sid group_sid;
     640           0 :         enum lsa_SidType type;
     641         257 :         uint32_t num_sids = 0;
     642         257 :         struct dom_sid *user_sids = NULL;
     643           0 :         bool is_null;
     644           0 :         bool ok;
     645             : 
     646         257 :         tmp_ctx = talloc_stackframe();
     647             : 
     648         257 :         ok = lookup_name_smbconf(tmp_ctx,
     649             :                                  unix_username,
     650             :                                  LOOKUP_NAME_ALL,
     651             :                                  &domain_name,
     652             :                                  &user_name,
     653             :                                  &user_sid,
     654             :                                  &type);
     655         257 :         if (!ok) {
     656           0 :                 status = NT_STATUS_NO_SUCH_USER;
     657           0 :                 goto done;
     658             :         }
     659             : 
     660         257 :         if (type != SID_NAME_USER) {
     661           0 :                 status = NT_STATUS_NO_SUCH_USER;
     662           0 :                 goto done;
     663             :         }
     664             : 
     665         257 :         ok = winbind_lookup_usersids(tmp_ctx,
     666             :                                      &user_sid,
     667             :                                      &num_sids,
     668             :                                      &user_sids);
     669             :         /* Check if winbind is running */
     670         257 :         if (ok) {
     671             :                 /*
     672             :                  * Winbind is running and the first element of the user_sids
     673             :                  * is the primary group.
     674             :                  */
     675         138 :                 if (num_sids > 0) {
     676         138 :                         group_sid = user_sids[0];
     677             :                 }
     678             :         } else {
     679             :                 /*
     680             :                  * Winbind is not running, try to create the group_sid from the
     681             :                  * passwd group id.
     682             :                  */
     683             : 
     684             :                 /*
     685             :                  * This can lead to a primary group of S-1-22-2-XX which
     686             :                  * will be rejected by other Samba code.
     687             :                  */
     688         119 :                 gid_to_sid(&group_sid, pwd->pw_gid);
     689             :         }
     690             : 
     691             :         /*
     692             :          * If we are a unix group, or a wellknown/builtin alias,
     693             :          * set the group_sid to the
     694             :          * 'Domain Users' RID of 513 which will always resolve to a
     695             :          * name.
     696             :          */
     697         451 :         if (sid_check_is_in_unix_groups(&group_sid) ||
     698         388 :             sid_check_is_in_builtin(&group_sid) ||
     699         194 :             sid_check_is_in_wellknown_domain(&group_sid)) {
     700         119 :                 if (sid_check_is_in_unix_users(&user_sid)) {
     701         112 :                         sid_compose(&group_sid,
     702         112 :                                     get_global_sam_sid(),
     703             :                                     DOMAIN_RID_USERS);
     704             :                 } else {
     705           7 :                         sid_copy(&domain_sid, &user_sid);
     706           7 :                         sid_split_rid(&domain_sid, NULL);
     707           7 :                         sid_compose(&group_sid,
     708             :                                     &domain_sid,
     709             :                                     DOMAIN_RID_USERS);
     710             :                 }
     711             :         }
     712             : 
     713             :         /* Make sure we have a valid group sid */
     714         257 :         is_null = is_null_sid(&group_sid);
     715         257 :         if (is_null) {
     716           0 :                 status = NT_STATUS_NO_SUCH_USER;
     717           0 :                 goto done;
     718             :         }
     719             : 
     720             :         /* Construct a netr_SamInfo3 from the information we have */
     721         257 :         info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3);
     722         257 :         if (!info3) {
     723           0 :                 status = NT_STATUS_NO_MEMORY;
     724           0 :                 goto done;
     725             :         }
     726             : 
     727         257 :         info3->base.account_name.string = talloc_strdup(info3, unix_username);
     728         257 :         if (info3->base.account_name.string == NULL) {
     729           0 :                 status = NT_STATUS_NO_MEMORY;
     730           0 :                 goto done;
     731             :         }
     732             : 
     733         257 :         info3->base.logon_domain.string = talloc_strdup(info3, domain_name);
     734         257 :         if (info3->base.logon_domain.string == NULL) {
     735           0 :                 status = NT_STATUS_NO_MEMORY;
     736           0 :                 goto done;
     737             :         }
     738             : 
     739         257 :         ZERO_STRUCT(domain_sid);
     740             : 
     741         257 :         status = SamInfo3_handle_sids(unix_username,
     742             :                                 &user_sid,
     743             :                                 &group_sid,
     744             :                                 info3,
     745             :                                 &domain_sid,
     746             :                                 extra);
     747             : 
     748         257 :         if (!NT_STATUS_IS_OK(status)) {
     749           0 :                 goto done;
     750             :         }
     751             : 
     752         257 :         info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
     753         257 :         if (info3->base.domain_sid == NULL) {
     754           0 :                 status = NT_STATUS_NO_MEMORY;
     755           0 :                 goto done;
     756             :         }
     757             : 
     758         257 :         ok = sid_peek_check_rid(&domain_sid, &group_sid,
     759         257 :                                 &info3->base.primary_gid);
     760         257 :         if (!ok) {
     761           0 :                 struct dom_sid_buf buf1, buf2, buf3;
     762             : 
     763           0 :                 DEBUG(1, ("The primary group domain sid(%s) does not "
     764             :                           "match the domain sid(%s) for %s(%s)\n",
     765             :                           dom_sid_str_buf(&group_sid, &buf1),
     766             :                           dom_sid_str_buf(&domain_sid, &buf2),
     767             :                           unix_username,
     768             :                           dom_sid_str_buf(&user_sid, &buf3)));
     769           0 :                 status = NT_STATUS_INVALID_SID;
     770           0 :                 goto done;
     771             :         }
     772             : 
     773         257 :         info3->base.acct_flags = ACB_NORMAL;
     774             : 
     775         257 :         if (num_sids) {
     776         138 :                 status = group_sids_to_info3(info3, user_sids, num_sids);
     777         138 :                 if (!NT_STATUS_IS_OK(status)) {
     778           0 :                         goto done;
     779             :                 }
     780             :         }
     781             : 
     782         257 :         *pinfo3 = talloc_move(mem_ctx, &info3);
     783             : 
     784         257 :         status = NT_STATUS_OK;
     785         257 : done:
     786         257 :         talloc_free(tmp_ctx);
     787             : 
     788         257 :         return status;
     789             : }

Generated by: LCOV version 1.14