LCOV - code coverage report
Current view: top level - source3/auth - server_info.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 198 323 61.3 %
Date: 2024-06-13 04:01:37 Functions: 9 12 75.0 %

          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        1664 : struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
      38             : {
      39             :         struct auth_serversupplied_info *result;
      40             : 
      41        1664 :         result = talloc_zero(mem_ctx, struct auth_serversupplied_info);
      42        1664 :         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        1664 :         result->utok.uid = -1;
      52        1664 :         result->utok.gid = -1;
      53             : 
      54        1664 :         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           0 : NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
      63             :                                 struct netr_SamInfo2 *sam2)
      64             : {
      65           0 :         struct netr_SamInfo3 *info3 = NULL;
      66             :         NTSTATUS status;
      67             : 
      68           0 :         status = copy_netr_SamInfo3(sam2,
      69           0 :                                     server_info->info3,
      70             :                                     &info3);
      71           0 :         if (!NT_STATUS_IS_OK(status)) {
      72           0 :                 return status;
      73             :         }
      74             : 
      75           0 :         if (server_info->session_key.length) {
      76           0 :                 memcpy(info3->base.key.key,
      77           0 :                        server_info->session_key.data,
      78           0 :                        MIN(sizeof(info3->base.key.key),
      79             :                            server_info->session_key.length));
      80             :         }
      81           0 :         if (server_info->lm_session_key.length) {
      82           0 :                 memcpy(info3->base.LMSessKey.key,
      83           0 :                        server_info->lm_session_key.data,
      84           0 :                        MIN(sizeof(info3->base.LMSessKey.key),
      85             :                            server_info->lm_session_key.length));
      86             :         }
      87             : 
      88           0 :         sam2->base = info3->base;
      89             : 
      90           0 :         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           2 : NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info,
      99             :                                 struct netr_SamInfo3 *sam3)
     100             : {
     101           2 :         struct netr_SamInfo3 *info3 = NULL;
     102             :         NTSTATUS status;
     103             : 
     104           2 :         status = copy_netr_SamInfo3(sam3,
     105           2 :                                     server_info->info3,
     106             :                                     &info3);
     107           2 :         if (!NT_STATUS_IS_OK(status)) {
     108           0 :                 return status;
     109             :         }
     110             : 
     111           2 :         if (server_info->session_key.length) {
     112           2 :                 memcpy(info3->base.key.key,
     113           2 :                        server_info->session_key.data,
     114           2 :                        MIN(sizeof(info3->base.key.key),
     115             :                            server_info->session_key.length));
     116             :         }
     117           2 :         if (server_info->lm_session_key.length) {
     118           1 :                 memcpy(info3->base.LMSessKey.key,
     119           1 :                        server_info->lm_session_key.data,
     120           1 :                        MIN(sizeof(info3->base.LMSessKey.key),
     121             :                            server_info->lm_session_key.length));
     122             :         }
     123             : 
     124           2 :         sam3->base = info3->base;
     125             : 
     126           2 :         sam3->sidcount               = 0;
     127           2 :         sam3->sids           = NULL;
     128             : 
     129           2 :         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             :         struct pdb_domain_info *dominfo;
     141           0 :         struct netr_SamInfo3 *info3 = NULL;
     142             :         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         902 : 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         902 :         uint32_t t = *count;
     202             : 
     203         902 :         *sids = talloc_realloc(mem_ctx, *sids, struct netr_SidAttr, t + 1);
     204         902 :         if (*sids == NULL) {
     205           0 :                 return NT_STATUS_NO_MEMORY;
     206             :         }
     207         902 :         (*sids)[t].sid = dom_sid_dup(*sids, asid);
     208         902 :         if ((*sids)[t].sid == NULL) {
     209           0 :                 return NT_STATUS_NO_MEMORY;
     210             :         }
     211         902 :         (*sids)[t].attributes = attributes;
     212         902 :         *count = t + 1;
     213             : 
     214         902 :         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         497 : static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
     221             :                                     const struct dom_sid *sids,
     222             :                                     size_t num_sids)
     223             : {
     224         497 :         uint32_t attributes = SE_GROUP_MANDATORY |
     225             :                                 SE_GROUP_ENABLED_BY_DEFAULT |
     226             :                                 SE_GROUP_ENABLED;
     227             :         struct samr_RidWithAttributeArray *groups;
     228             :         struct dom_sid *domain_sid;
     229             :         unsigned int i;
     230             :         NTSTATUS status;
     231             :         uint32_t rid;
     232             :         bool ok;
     233             : 
     234         497 :         domain_sid = info3->base.domain_sid;
     235         497 :         groups = &info3->base.groups;
     236             : 
     237         497 :         groups->rids = talloc_array(info3,
     238             :                                     struct samr_RidWithAttribute, num_sids);
     239         497 :         if (!groups->rids) {
     240           0 :                 return NT_STATUS_NO_MEMORY;
     241             :         }
     242             : 
     243        1484 :         for (i = 0; i < num_sids; i++) {
     244         987 :                 ok = sid_peek_check_rid(domain_sid, &sids[i], &rid);
     245         987 :                 if (ok) {
     246             :                         /* store domain group rid */
     247          85 :                         groups->rids[groups->count].rid = rid;
     248          85 :                         groups->rids[groups->count].attributes = attributes;
     249          85 :                         groups->count++;
     250          85 :                         continue;
     251             :                 }
     252             : 
     253             :                 /* if this wasn't a domain sid, add it as extra sid */
     254         902 :                 status = append_netr_SidAttr(info3, &info3->sids,
     255             :                                              &info3->sidcount,
     256         902 :                                              &sids[i], attributes);
     257         902 :                 if (!NT_STATUS_IS_OK(status)) {
     258           0 :                         return status;
     259             :                 }
     260             :         }
     261             : 
     262         497 :         return NT_STATUS_OK;
     263             : }
     264             : 
     265             : /*
     266             :  * Merge resource SIDs, if any, into the passed in info3 structure.
     267             :  */
     268             : 
     269         617 : static NTSTATUS merge_resource_sids(const struct PAC_LOGON_INFO *logon_info,
     270             :                                 struct netr_SamInfo3 *info3)
     271             : {
     272         617 :         uint32_t i = 0;
     273         617 :         const struct PAC_DOMAIN_GROUP_MEMBERSHIP *rg = NULL;
     274             : 
     275         617 :         if (logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS) {
     276           0 :                 rg = &logon_info->resource_groups;
     277             :         }
     278             : 
     279         617 :         if (rg == NULL) {
     280         617 :                 return NT_STATUS_OK;
     281             :         }
     282             : 
     283           0 :         if (rg->domain_sid == NULL) {
     284           0 :                 DEBUG(10, ("Missing Resource Group Domain SID\n"));
     285           0 :                 return NT_STATUS_INVALID_PARAMETER;
     286             :         }
     287             : 
     288             :         /* The IDL layer would be a better place to check this, but to
     289             :          * guard the integer addition below, we double-check */
     290           0 :         if (rg->groups.count > 65535) {
     291           0 :                 DEBUG(10, ("Too much Resource Group RIDs %u\n",
     292             :                           (unsigned)rg->groups.count));
     293           0 :                 return NT_STATUS_INVALID_PARAMETER;
     294             :         }
     295             : 
     296             :         /*
     297             :          * If there are any resource groups (SID Compression) add
     298             :          * them to the extra sids portion of the info3 in the PAC.
     299             :          *
     300             :          * This makes the info3 look like it would if we got the info
     301             :          * from the DC rather than the PAC.
     302             :          */
     303             : 
     304             :         /*
     305             :          * Construct a SID for each RID in the list and then append it
     306             :          * to the info3.
     307             :          */
     308           0 :         for (i = 0; i < rg->groups.count; i++) {
     309             :                 NTSTATUS status;
     310             :                 struct dom_sid new_sid;
     311           0 :                 uint32_t attributes = rg->groups.rids[i].attributes;
     312             :                 struct dom_sid_buf buf;
     313             : 
     314           0 :                 sid_compose(&new_sid,
     315           0 :                             rg->domain_sid,
     316           0 :                             rg->groups.rids[i].rid);
     317             : 
     318           0 :                 DEBUG(10, ("Adding SID %s to extra SIDS\n",
     319             :                            dom_sid_str_buf(&new_sid, &buf)));
     320             : 
     321           0 :                 status = append_netr_SidAttr(info3, &info3->sids,
     322             :                                         &info3->sidcount,
     323             :                                         &new_sid,
     324             :                                         attributes);
     325           0 :                 if (!NT_STATUS_IS_OK(status)) {
     326           0 :                         DEBUG(1, ("failed to append SID %s to extra SIDS: %s\n",
     327             :                                 dom_sid_str_buf(&new_sid, &buf),
     328             :                                 nt_errstr(status)));
     329           0 :                         return status;
     330             :                 }
     331             :         }
     332             : 
     333           0 :         return NT_STATUS_OK;
     334             : }
     335             : 
     336             : /*
     337             :  * Create a copy of an info3 struct from the struct PAC_LOGON_INFO,
     338             :  * then merge resource SIDs, if any, into it. If successful return
     339             :  * the created info3 struct.
     340             :  */
     341             : 
     342           0 : NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx,
     343             :                                         const struct PAC_LOGON_INFO *logon_info,
     344             :                                         struct netr_SamInfo3 **pp_info3)
     345             : {
     346             :         NTSTATUS status;
     347           0 :         struct netr_SamInfo3 *info3 = NULL;
     348             : 
     349           0 :         status = copy_netr_SamInfo3(mem_ctx,
     350             :                                     &logon_info->info3,
     351             :                                     &info3);
     352           0 :         if (!NT_STATUS_IS_OK(status)) {
     353           0 :                 return status;
     354             :         }
     355             : 
     356           0 :         status = merge_resource_sids(logon_info, info3);
     357           0 :         if (!NT_STATUS_IS_OK(status)) {
     358           0 :                 TALLOC_FREE(info3);
     359           0 :                 return status;
     360             :         }
     361           0 :         *pp_info3 = info3;
     362           0 :         return NT_STATUS_OK;
     363             : }
     364             : 
     365             : /*
     366             :  * Create a copy of an info6 struct from the PAC_UPN_DNS_INFO and PAC_LOGON_INFO
     367             :  * then merge resource SIDs, if any, into it. If successful return the created
     368             :  * info6 struct.
     369             :  */
     370         617 : NTSTATUS create_info6_from_pac(TALLOC_CTX *mem_ctx,
     371             :                                const struct PAC_LOGON_INFO *logon_info,
     372             :                                const struct PAC_UPN_DNS_INFO *upn_dns_info,
     373             :                                struct netr_SamInfo6 **pp_info6)
     374             : {
     375             :         NTSTATUS status;
     376         617 :         struct netr_SamInfo6 *info6 = NULL;
     377         617 :         struct netr_SamInfo3 *info3 = NULL;
     378             : 
     379         617 :         info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
     380         617 :         if (info6 == NULL) {
     381           0 :                 return NT_STATUS_NO_MEMORY;
     382             :         }
     383             : 
     384         617 :         status = copy_netr_SamInfo3(info6,
     385             :                                     &logon_info->info3,
     386             :                                     &info3);
     387         617 :         if (!NT_STATUS_IS_OK(status)) {
     388           0 :                 TALLOC_FREE(info6);
     389           0 :                 return status;
     390             :         }
     391             : 
     392         617 :         status = merge_resource_sids(logon_info, info3);
     393         617 :         if (!NT_STATUS_IS_OK(status)) {
     394           0 :                 TALLOC_FREE(info6);
     395           0 :                 return status;
     396             :         }
     397             : 
     398         617 :         info6->base = info3->base;
     399         617 :         info6->sids = info3->sids;
     400         617 :         info6->sidcount = info3->sidcount;
     401             : 
     402         617 :         if (upn_dns_info != NULL) {
     403         801 :                 info6->dns_domainname.string = talloc_strdup(info6,
     404         267 :                                 upn_dns_info->dns_domain_name);
     405         534 :                 if (info6->dns_domainname.string == NULL) {
     406           0 :                         TALLOC_FREE(info6);
     407           0 :                         return NT_STATUS_NO_MEMORY;
     408             :                 }
     409         801 :                 info6->principal_name.string = talloc_strdup(info6,
     410         267 :                                 upn_dns_info->upn_name);
     411         534 :                 if (info6->principal_name.string == NULL) {
     412           0 :                         TALLOC_FREE(info6);
     413           0 :                         return NT_STATUS_NO_MEMORY;
     414             :                 }
     415             :         }
     416             : 
     417         617 :         *pp_info6 = info6;
     418         617 :         return NT_STATUS_OK;
     419             : }
     420             : 
     421             : /*
     422             :  * Check if this is a "Unix Users" domain user, or a
     423             :  * "Unix Groups" domain group, we need to handle it
     424             :  * in a special way if that's the case.
     425             :  */
     426             : 
     427         531 : static NTSTATUS SamInfo3_handle_sids(const char *username,
     428             :                         const struct dom_sid *user_sid,
     429             :                         const struct dom_sid *group_sid,
     430             :                         struct netr_SamInfo3 *info3,
     431             :                         struct dom_sid *domain_sid,
     432             :                         struct extra_auth_info *extra)
     433             : {
     434             :         struct dom_sid_buf buf;
     435             : 
     436         531 :         if (sid_check_is_in_unix_users(user_sid)) {
     437             :                 /* in info3 you can only set rids for the user and the
     438             :                  * primary group, and the domain sid must be that of
     439             :                  * the sam domain.
     440             :                  *
     441             :                  * Store a completely bogus value here.
     442             :                  * The real SID is stored in the extra sids.
     443             :                  * Other code will know to look there if (-1) is found
     444             :                  */
     445          32 :                 info3->base.rid = (uint32_t)(-1);
     446          32 :                 sid_copy(&extra->user_sid, user_sid);
     447             : 
     448          32 :                 DEBUG(10, ("Unix User found. Rid marked as "
     449             :                         "special and sid (%s) saved as extra sid\n",
     450             :                         dom_sid_str_buf(user_sid, &buf)));
     451             :         } else {
     452         499 :                 sid_copy(domain_sid, user_sid);
     453         499 :                 sid_split_rid(domain_sid, &info3->base.rid);
     454             :         }
     455             : 
     456         531 :         if (is_null_sid(domain_sid)) {
     457          32 :                 sid_copy(domain_sid, get_global_sam_sid());
     458             :         }
     459             : 
     460             :         /* check if this is a "Unix Groups" domain group,
     461             :          * if so we need special handling */
     462         531 :         if (sid_check_is_in_unix_groups(group_sid)) {
     463             :                 /* in info3 you can only set rids for the user and the
     464             :                  * primary group, and the domain sid must be that of
     465             :                  * the sam domain.
     466             :                  *
     467             :                  * Store a completely bogus value here.
     468             :                  * The real SID is stored in the extra sids.
     469             :                  * Other code will know to look there if (-1) is found
     470             :                  */
     471           0 :                 info3->base.primary_gid = (uint32_t)(-1);
     472           0 :                 sid_copy(&extra->pgid_sid, group_sid);
     473             : 
     474           0 :                 DEBUG(10, ("Unix Group found. Rid marked as "
     475             :                         "special and sid (%s) saved as extra sid\n",
     476             :                         dom_sid_str_buf(group_sid, &buf)));
     477             :         } else {
     478         531 :                 bool ok = sid_peek_check_rid(domain_sid, group_sid,
     479             :                                         &info3->base.primary_gid);
     480         531 :                 if (!ok) {
     481             :                         struct dom_sid_buf buf2, buf3;
     482           0 :                         DEBUG(1, ("The primary group domain sid(%s) does not "
     483             :                                 "match the domain sid(%s) for %s(%s)\n",
     484             :                                 dom_sid_str_buf(group_sid, &buf),
     485             :                                 dom_sid_str_buf(domain_sid, &buf2),
     486             :                                 username,
     487             :                                 dom_sid_str_buf(user_sid, &buf3)));
     488           0 :                         return NT_STATUS_INVALID_SID;
     489             :                 }
     490             :         }
     491         531 :         return NT_STATUS_OK;
     492             : }
     493             : 
     494             : #define RET_NOMEM(ptr) do { \
     495             :         if (!ptr) { \
     496             :                 TALLOC_FREE(info3); \
     497             :                 return NT_STATUS_NO_MEMORY; \
     498             :         } } while(0)
     499             : 
     500         457 : NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
     501             :                           struct samu *samu,
     502             :                           const char *login_server,
     503             :                           struct netr_SamInfo3 **_info3,
     504             :                           struct extra_auth_info *extra)
     505             : {
     506             :         struct netr_SamInfo3 *info3;
     507             :         const struct dom_sid *user_sid;
     508             :         const struct dom_sid *group_sid;
     509         457 :         struct dom_sid domain_sid = {0};
     510             :         struct dom_sid *group_sids;
     511         457 :         uint32_t num_group_sids = 0;
     512             :         const char *tmp;
     513             :         gid_t *gids;
     514             :         NTSTATUS status;
     515             : 
     516         457 :         user_sid = pdb_get_user_sid(samu);
     517         457 :         group_sid = pdb_get_group_sid(samu);
     518             : 
     519         457 :         if (!user_sid || !group_sid) {
     520           0 :                 DEBUG(1, ("Sam account is missing sids!\n"));
     521           0 :                 return NT_STATUS_UNSUCCESSFUL;
     522             :         }
     523             : 
     524         457 :         info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
     525         457 :         if (!info3) {
     526           0 :                 return NT_STATUS_NO_MEMORY;
     527             :         }
     528             : 
     529         457 :         status = SamInfo3_handle_sids(pdb_get_username(samu),
     530             :                                 user_sid,
     531             :                                 group_sid,
     532             :                                 info3,
     533             :                                 &domain_sid,
     534             :                                 extra);
     535             : 
     536         457 :         if (!NT_STATUS_IS_OK(status)) {
     537           0 :                 TALLOC_FREE(info3);
     538           0 :                 return status;
     539             :         }
     540             : 
     541         457 :         unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
     542         457 :         unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
     543         457 :         unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
     544         457 :         unix_to_nt_time(&info3->base.last_password_change,
     545             :                         pdb_get_pass_last_set_time(samu));
     546         457 :         unix_to_nt_time(&info3->base.allow_password_change,
     547             :                         pdb_get_pass_can_change_time(samu));
     548         457 :         unix_to_nt_time(&info3->base.force_password_change,
     549             :                         pdb_get_pass_must_change_time(samu));
     550             : 
     551         457 :         tmp = pdb_get_username(samu);
     552         457 :         if (tmp) {
     553         457 :                 info3->base.account_name.string      = talloc_strdup(info3, tmp);
     554         457 :                 RET_NOMEM(info3->base.account_name.string);
     555             :         }
     556         457 :         tmp = pdb_get_fullname(samu);
     557         457 :         if (tmp) {
     558         457 :                 info3->base.full_name.string = talloc_strdup(info3, tmp);
     559         457 :                 RET_NOMEM(info3->base.full_name.string);
     560             :         }
     561         457 :         tmp = pdb_get_logon_script(samu);
     562         457 :         if (tmp) {
     563         457 :                 info3->base.logon_script.string = talloc_strdup(info3, tmp);
     564         457 :                 RET_NOMEM(info3->base.logon_script.string);
     565             :         }
     566         457 :         tmp = pdb_get_profile_path(samu);
     567         457 :         if (tmp) {
     568         457 :                 info3->base.profile_path.string      = talloc_strdup(info3, tmp);
     569         457 :                 RET_NOMEM(info3->base.profile_path.string);
     570             :         }
     571         457 :         tmp = pdb_get_homedir(samu);
     572         457 :         if (tmp) {
     573         457 :                 info3->base.home_directory.string = talloc_strdup(info3, tmp);
     574         457 :                 RET_NOMEM(info3->base.home_directory.string);
     575             :         }
     576         457 :         tmp = pdb_get_dir_drive(samu);
     577         457 :         if (tmp) {
     578         456 :                 info3->base.home_drive.string = talloc_strdup(info3, tmp);
     579         456 :                 RET_NOMEM(info3->base.home_drive.string);
     580             :         }
     581             : 
     582         457 :         info3->base.logon_count      = pdb_get_logon_count(samu);
     583         457 :         info3->base.bad_password_count = pdb_get_bad_password_count(samu);
     584             : 
     585         457 :         info3->base.logon_domain.string = talloc_strdup(info3,
     586             :                                                   pdb_get_domain(samu));
     587         457 :         RET_NOMEM(info3->base.logon_domain.string);
     588             : 
     589         457 :         info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
     590         457 :         RET_NOMEM(info3->base.domain_sid);
     591             : 
     592         457 :         status = pdb_enum_group_memberships(mem_ctx, samu,
     593             :                                             &group_sids, &gids,
     594             :                                             &num_group_sids);
     595         457 :         if (!NT_STATUS_IS_OK(status)) {
     596           0 :                 DEBUG(1, ("Failed to get groups from sam account.\n"));
     597           0 :                 TALLOC_FREE(info3);
     598           0 :                 return status;
     599             :         }
     600             : 
     601         457 :         if (num_group_sids) {
     602         457 :                 status = group_sids_to_info3(info3, group_sids, num_group_sids);
     603         457 :                 if (!NT_STATUS_IS_OK(status)) {
     604           0 :                         TALLOC_FREE(info3);
     605           0 :                         return status;
     606             :                 }
     607             :         }
     608             : 
     609             :         /* We don't need sids and gids after the conversion */
     610         457 :         TALLOC_FREE(group_sids);
     611         457 :         TALLOC_FREE(gids);
     612         457 :         num_group_sids = 0;
     613             : 
     614             :         /* FIXME: should we add other flags ? */
     615         457 :         info3->base.user_flags = NETLOGON_EXTRA_SIDS;
     616             : 
     617         457 :         if (login_server) {
     618         457 :                 info3->base.logon_server.string = talloc_strdup(info3, login_server);
     619         457 :                 RET_NOMEM(info3->base.logon_server.string);
     620             :         }
     621             : 
     622         457 :         info3->base.acct_flags = pdb_get_acct_ctrl(samu);
     623             : 
     624         457 :         *_info3 = info3;
     625         457 :         return NT_STATUS_OK;
     626             : }
     627             : 
     628          74 : NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
     629             :                             const char *unix_username,
     630             :                             const struct passwd *pwd,
     631             :                             struct netr_SamInfo3 **pinfo3,
     632             :                             struct extra_auth_info *extra)
     633             : {
     634             :         struct netr_SamInfo3 *info3;
     635             :         NTSTATUS status;
     636             :         TALLOC_CTX *tmp_ctx;
     637          74 :         const char *domain_name = NULL;
     638          74 :         const char *user_name = NULL;
     639             :         struct dom_sid domain_sid;
     640             :         struct dom_sid user_sid;
     641             :         struct dom_sid group_sid;
     642             :         enum lsa_SidType type;
     643          74 :         uint32_t num_sids = 0;
     644          74 :         struct dom_sid *user_sids = NULL;
     645             :         bool is_null;
     646             :         bool ok;
     647             : 
     648          74 :         tmp_ctx = talloc_stackframe();
     649             : 
     650          74 :         ok = lookup_name_smbconf(tmp_ctx,
     651             :                                  unix_username,
     652             :                                  LOOKUP_NAME_ALL,
     653             :                                  &domain_name,
     654             :                                  &user_name,
     655             :                                  &user_sid,
     656             :                                  &type);
     657          74 :         if (!ok) {
     658           0 :                 status = NT_STATUS_NO_SUCH_USER;
     659           0 :                 goto done;
     660             :         }
     661             : 
     662          74 :         if (type != SID_NAME_USER) {
     663           0 :                 status = NT_STATUS_NO_SUCH_USER;
     664           0 :                 goto done;
     665             :         }
     666             : 
     667          74 :         ok = winbind_lookup_usersids(tmp_ctx,
     668             :                                      &user_sid,
     669             :                                      &num_sids,
     670             :                                      &user_sids);
     671             :         /* Check if winbind is running */
     672          74 :         if (ok) {
     673             :                 /*
     674             :                  * Winbind is running and the first element of the user_sids
     675             :                  * is the primary group.
     676             :                  */
     677          40 :                 if (num_sids > 0) {
     678          40 :                         group_sid = user_sids[0];
     679             :                 }
     680             :         } else {
     681             :                 /*
     682             :                  * Winbind is not running, try to create the group_sid from the
     683             :                  * passwd group id.
     684             :                  */
     685             : 
     686             :                 /*
     687             :                  * This can lead to a primary group of S-1-22-2-XX which
     688             :                  * will be rejected by other Samba code.
     689             :                  */
     690          34 :                 gid_to_sid(&group_sid, pwd->pw_gid);
     691             :         }
     692             : 
     693             :         /*
     694             :          * If we are a unix group, or a wellknown/builtin alias,
     695             :          * set the group_sid to the
     696             :          * 'Domain Users' RID of 513 which will always resolve to a
     697             :          * name.
     698             :          */
     699         130 :         if (sid_check_is_in_unix_groups(&group_sid) ||
     700         112 :             sid_check_is_in_builtin(&group_sid) ||
     701          56 :             sid_check_is_in_wellknown_domain(&group_sid)) {
     702          34 :                 if (sid_check_is_in_unix_users(&user_sid)) {
     703          32 :                         sid_compose(&group_sid,
     704          32 :                                     get_global_sam_sid(),
     705             :                                     DOMAIN_RID_USERS);
     706             :                 } else {
     707           2 :                         sid_copy(&domain_sid, &user_sid);
     708           2 :                         sid_split_rid(&domain_sid, NULL);
     709           2 :                         sid_compose(&group_sid,
     710             :                                     &domain_sid,
     711             :                                     DOMAIN_RID_USERS);
     712             :                 }
     713             :         }
     714             : 
     715             :         /* Make sure we have a valid group sid */
     716          74 :         is_null = is_null_sid(&group_sid);
     717          74 :         if (is_null) {
     718           0 :                 status = NT_STATUS_NO_SUCH_USER;
     719           0 :                 goto done;
     720             :         }
     721             : 
     722             :         /* Construct a netr_SamInfo3 from the information we have */
     723          74 :         info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3);
     724          74 :         if (!info3) {
     725           0 :                 status = NT_STATUS_NO_MEMORY;
     726           0 :                 goto done;
     727             :         }
     728             : 
     729          74 :         info3->base.account_name.string = talloc_strdup(info3, unix_username);
     730          74 :         if (info3->base.account_name.string == NULL) {
     731           0 :                 status = NT_STATUS_NO_MEMORY;
     732           0 :                 goto done;
     733             :         }
     734             : 
     735          74 :         info3->base.logon_domain.string = talloc_strdup(info3, domain_name);
     736          74 :         if (info3->base.logon_domain.string == NULL) {
     737           0 :                 status = NT_STATUS_NO_MEMORY;
     738           0 :                 goto done;
     739             :         }
     740             : 
     741          74 :         ZERO_STRUCT(domain_sid);
     742             : 
     743          74 :         status = SamInfo3_handle_sids(unix_username,
     744             :                                 &user_sid,
     745             :                                 &group_sid,
     746             :                                 info3,
     747             :                                 &domain_sid,
     748             :                                 extra);
     749             : 
     750          74 :         if (!NT_STATUS_IS_OK(status)) {
     751           0 :                 goto done;
     752             :         }
     753             : 
     754          74 :         info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
     755          74 :         if (info3->base.domain_sid == NULL) {
     756           0 :                 status = NT_STATUS_NO_MEMORY;
     757           0 :                 goto done;
     758             :         }
     759             : 
     760          74 :         ok = sid_peek_check_rid(&domain_sid, &group_sid,
     761          74 :                                 &info3->base.primary_gid);
     762          74 :         if (!ok) {
     763             :                 struct dom_sid_buf buf1, buf2, buf3;
     764             : 
     765           0 :                 DEBUG(1, ("The primary group domain sid(%s) does not "
     766             :                           "match the domain sid(%s) for %s(%s)\n",
     767             :                           dom_sid_str_buf(&group_sid, &buf1),
     768             :                           dom_sid_str_buf(&domain_sid, &buf2),
     769             :                           unix_username,
     770             :                           dom_sid_str_buf(&user_sid, &buf3)));
     771           0 :                 status = NT_STATUS_INVALID_SID;
     772           0 :                 goto done;
     773             :         }
     774             : 
     775          74 :         info3->base.acct_flags = ACB_NORMAL;
     776             : 
     777          74 :         if (num_sids) {
     778          40 :                 status = group_sids_to_info3(info3, user_sids, num_sids);
     779          40 :                 if (!NT_STATUS_IS_OK(status)) {
     780           0 :                         goto done;
     781             :                 }
     782             :         }
     783             : 
     784          74 :         *pinfo3 = talloc_move(mem_ctx, &info3);
     785             : 
     786          74 :         status = NT_STATUS_OK;
     787          74 : done:
     788          74 :         talloc_free(tmp_ctx);
     789             : 
     790          74 :         return status;
     791             : }

Generated by: LCOV version 1.13