LCOV - code coverage report
Current view: top level - source3/libnet - libnet_dssync_passdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 928 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 29 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Guenther Deschner <gd@samba.org> 2008
       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 "system/passwd.h"
      22             : #include "libnet/libnet_dssync.h"
      23             : #include "../libcli/security/security.h"
      24             : #include "../libds/common/flags.h"
      25             : #include "../librpc/gen_ndr/ndr_drsuapi.h"
      26             : #include "util_tdb.h"
      27             : #include "dbwrap/dbwrap.h"
      28             : #include "dbwrap/dbwrap_rbt.h"
      29             : #include "../libds/common/flag_mapping.h"
      30             : #include "passdb.h"
      31             : #include "lib/util/base64.h"
      32             : #include "lib/util/string_wrappers.h"
      33             : 
      34             : /****************************************************************
      35             : ****************************************************************/
      36             : 
      37             : struct dssync_passdb {
      38             :         struct pdb_methods *methods;
      39             :         struct db_context *all;
      40             :         struct db_context *aliases;
      41             :         struct db_context *groups;
      42             : };
      43             : 
      44             : struct dssync_passdb_obj {
      45             :         struct dssync_passdb_obj *self;
      46             :         uint32_t type;
      47             :         struct drsuapi_DsReplicaObjectListItemEx *cur;
      48             :         TDB_DATA key;
      49             :         TDB_DATA data;
      50             :         struct db_context *members;
      51             : };
      52             : 
      53             : struct dssync_passdb_mem {
      54             :         struct dssync_passdb_mem *self;
      55             :         bool active;
      56             :         struct drsuapi_DsReplicaObjectIdentifier3 *cur;
      57             :         struct dssync_passdb_obj *obj;
      58             :         TDB_DATA key;
      59             :         TDB_DATA data;
      60             : };
      61             : 
      62           0 : static NTSTATUS dssync_insert_obj(struct dssync_passdb *pctx,
      63             :                                   struct db_context *db,
      64             :                                   struct dssync_passdb_obj *obj)
      65             : {
      66           0 :         NTSTATUS status;
      67           0 :         struct db_record *rec;
      68           0 :         TDB_DATA value;
      69             : 
      70           0 :         rec = dbwrap_fetch_locked(db, talloc_tos(), obj->key);
      71           0 :         if (rec == NULL) {
      72           0 :                 return NT_STATUS_NO_MEMORY;
      73             :         }
      74             : 
      75           0 :         value = dbwrap_record_get_value(rec);
      76           0 :         if (value.dsize != 0) {
      77           0 :                 abort();
      78             :         }
      79             : 
      80           0 :         status = dbwrap_record_store(rec, obj->data, TDB_INSERT);
      81           0 :         if (!NT_STATUS_IS_OK(status)) {
      82           0 :                 TALLOC_FREE(rec);
      83           0 :                 return status;
      84             :         }
      85           0 :         TALLOC_FREE(rec);
      86           0 :         return NT_STATUS_OK;
      87             : }
      88             : 
      89           0 : static struct dssync_passdb_obj *dssync_parse_obj(const TDB_DATA data)
      90             : {
      91           0 :         struct dssync_passdb_obj *obj;
      92             : 
      93           0 :         if (data.dsize != sizeof(obj)) {
      94           0 :                 return NULL;
      95             :         }
      96             : 
      97             :         /*
      98             :          * we need to copy the pointer to avoid alignment problems
      99             :          * on some systems.
     100             :          */
     101           0 :         memcpy(&obj, data.dptr, sizeof(obj));
     102             : 
     103           0 :         return talloc_get_type_abort(obj, struct dssync_passdb_obj);
     104             : }
     105             : 
     106           0 : static struct dssync_passdb_obj *dssync_search_obj_by_guid(struct dssync_passdb *pctx,
     107             :                                                            struct db_context *db,
     108             :                                                            const struct GUID *guid)
     109             : {
     110           0 :         struct dssync_passdb_obj *obj;
     111           0 :         TDB_DATA key;
     112           0 :         TDB_DATA data;
     113           0 :         NTSTATUS status;
     114             : 
     115           0 :         key = make_tdb_data((const uint8_t *)(const void *)guid,
     116             :                              sizeof(*guid));
     117             : 
     118           0 :         status = dbwrap_fetch(db, talloc_tos(), key, &data);
     119           0 :         if (!NT_STATUS_IS_OK(status)) {
     120           0 :                 return NULL;
     121             :         }
     122             : 
     123           0 :         obj = dssync_parse_obj(data);
     124           0 :         return obj;
     125             : }
     126             : 
     127           0 : static NTSTATUS dssync_create_obj(struct dssync_passdb *pctx,
     128             :                                   struct db_context *db,
     129             :                                   uint32_t type,
     130             :                                   struct drsuapi_DsReplicaObjectListItemEx *cur,
     131             :                                   struct dssync_passdb_obj **_obj)
     132             : {
     133           0 :         NTSTATUS status;
     134           0 :         struct dssync_passdb_obj *obj;
     135             : 
     136           0 :         obj = talloc_zero(pctx, struct dssync_passdb_obj);
     137           0 :         if (obj == NULL) {
     138           0 :                 return NT_STATUS_NO_MEMORY;
     139             :         }
     140           0 :         obj->self = obj;
     141           0 :         obj->cur = cur;
     142           0 :         obj->type = type;
     143           0 :         obj->key = make_tdb_data((const uint8_t *)(void *)&cur->object.identifier->guid,
     144             :                                    sizeof(cur->object.identifier->guid));
     145           0 :         obj->data = make_tdb_data((const uint8_t *)(void *)&obj->self,
     146             :                                   sizeof(obj->self));
     147             : 
     148           0 :         obj->members = db_open_rbt(obj);
     149           0 :         if (obj->members == NULL) {
     150           0 :                 return NT_STATUS_NO_MEMORY;
     151             :         }
     152             : 
     153           0 :         status = dssync_insert_obj(pctx, db, obj);
     154           0 :         if (!NT_STATUS_IS_OK(status)) {
     155           0 :                 TALLOC_FREE(obj);
     156           0 :                 return status;
     157             :         }
     158           0 :         *_obj = obj;
     159           0 :         return NT_STATUS_OK;
     160             : }
     161             : 
     162           0 : static NTSTATUS dssync_insert_mem(struct dssync_passdb *pctx,
     163             :                                   struct dssync_passdb_obj *obj,
     164             :                                   struct dssync_passdb_mem *mem)
     165             : {
     166           0 :         NTSTATUS status;
     167           0 :         struct db_record *rec;
     168           0 :         TDB_DATA value;
     169             : 
     170           0 :         rec = dbwrap_fetch_locked(obj->members, talloc_tos(), mem->key);
     171           0 :         if (rec == NULL) {
     172           0 :                 return NT_STATUS_NO_MEMORY;
     173             :         }
     174             : 
     175           0 :         value = dbwrap_record_get_value(rec);
     176           0 :         if (value.dsize != 0) {
     177           0 :                 abort();
     178             :         }
     179             : 
     180           0 :         status = dbwrap_record_store(rec, mem->data, TDB_INSERT);
     181           0 :         if (!NT_STATUS_IS_OK(status)) {
     182           0 :                 TALLOC_FREE(rec);
     183           0 :                 return status;
     184             :         }
     185           0 :         TALLOC_FREE(rec);
     186           0 :         return NT_STATUS_OK;
     187             : }
     188             : 
     189           0 : static NTSTATUS dssync_create_mem(struct dssync_passdb *pctx,
     190             :                                   struct dssync_passdb_obj *obj,
     191             :                                   bool active,
     192             :                                   struct drsuapi_DsReplicaObjectIdentifier3 *cur,
     193             :                                   struct dssync_passdb_mem **_mem)
     194             : {
     195           0 :         NTSTATUS status;
     196           0 :         struct dssync_passdb_mem *mem;
     197             : 
     198           0 :         mem = talloc_zero(pctx, struct dssync_passdb_mem);
     199           0 :         if (mem == NULL) {
     200           0 :                 return NT_STATUS_NO_MEMORY;
     201             :         }
     202           0 :         mem->self = mem;
     203           0 :         mem->cur = cur;
     204           0 :         mem->active = active;
     205           0 :         mem->obj = NULL;
     206           0 :         mem->key = make_tdb_data((const uint8_t *)(void *)&cur->guid,
     207             :                                    sizeof(cur->guid));
     208           0 :         mem->data = make_tdb_data((const uint8_t *)(void *)&mem->self,
     209             :                                   sizeof(mem->self));
     210             : 
     211           0 :         status = dssync_insert_mem(pctx, obj, mem);
     212           0 :         if (!NT_STATUS_IS_OK(status)) {
     213           0 :                 TALLOC_FREE(obj);
     214           0 :                 return status;
     215             :         }
     216           0 :         *_mem = mem;
     217           0 :         return NT_STATUS_OK;
     218             : }
     219             : 
     220           0 : static struct dssync_passdb_mem *dssync_parse_mem(const TDB_DATA data)
     221             : {
     222           0 :         struct dssync_passdb_mem *mem;
     223             : 
     224           0 :         if (data.dsize != sizeof(mem)) {
     225           0 :                 return NULL;
     226             :         }
     227             : 
     228             :         /*
     229             :          * we need to copy the pointer to avoid alignment problems
     230             :          * on some systems.
     231             :          */
     232           0 :         memcpy(&mem, data.dptr, sizeof(mem));
     233             : 
     234           0 :         return talloc_get_type_abort(mem, struct dssync_passdb_mem);
     235             : }
     236             : 
     237           0 : static NTSTATUS passdb_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
     238             :                                struct replUpToDateVectorBlob **pold_utdv)
     239             : {
     240           0 :         NTSTATUS status;
     241           0 :         struct dssync_passdb *pctx;
     242             : 
     243           0 :         pctx = talloc_zero(mem_ctx, struct dssync_passdb);
     244           0 :         if (pctx == NULL) {
     245           0 :                 return NT_STATUS_NO_MEMORY;
     246             :         }
     247             : 
     248           0 :         if (ctx->output_filename) {
     249           0 :                 status = make_pdb_method_name(&pctx->methods, ctx->output_filename);
     250             :         } else {
     251           0 :                 status = make_pdb_method_name(&pctx->methods, lp_passdb_backend());
     252             :         }
     253             : 
     254           0 :         if (!NT_STATUS_IS_OK(status)) {
     255           0 :                 return status;
     256             :         }
     257             : 
     258           0 :         pctx->all = db_open_rbt(pctx);
     259           0 :         if (pctx->all == NULL) {
     260           0 :                 return NT_STATUS_NO_MEMORY;
     261             :         }
     262           0 :         pctx->aliases = db_open_rbt(pctx);
     263           0 :         if (pctx->aliases == NULL) {
     264           0 :                 return NT_STATUS_NO_MEMORY;
     265             :         }
     266           0 :         pctx->groups = db_open_rbt(pctx);
     267           0 :         if (pctx->groups == NULL) {
     268           0 :                 return NT_STATUS_NO_MEMORY;
     269             :         }
     270             : 
     271           0 :         ctx->private_data = pctx;
     272             : 
     273           0 :         return status;
     274             : }
     275             : 
     276             : /****************************************************************
     277             : ****************************************************************/
     278             : 
     279             : struct dssync_passdb_traverse_amembers {
     280             :         struct dssync_context *ctx;
     281             :         struct dssync_passdb_obj *obj;
     282             :         const char *name;
     283             :         uint32_t idx;
     284             : };
     285             : 
     286             : struct dssync_passdb_traverse_aliases {
     287             :         struct dssync_context *ctx;
     288             :         const char *name;
     289             :         uint32_t idx;
     290             : };
     291             : 
     292           0 : static int dssync_passdb_traverse_amembers(struct db_record *rec,
     293             :                                            void *private_data)
     294             : {
     295           0 :         struct dssync_passdb_traverse_amembers *state =
     296             :                 (struct dssync_passdb_traverse_amembers *)private_data;
     297           0 :         struct dssync_passdb *pctx =
     298           0 :                 talloc_get_type_abort(state->ctx->private_data,
     299             :                 struct dssync_passdb);
     300           0 :         struct dssync_passdb_mem *mem;
     301           0 :         NTSTATUS status;
     302           0 :         struct dom_sid alias_sid;
     303           0 :         struct dom_sid member_sid;
     304           0 :         struct dom_sid_buf buf1, buf2;
     305           0 :         const char *member_dn;
     306           0 :         size_t num_members;
     307           0 :         size_t i;
     308           0 :         struct dom_sid *members;
     309           0 :         bool is_member = false;
     310           0 :         const char *action;
     311           0 :         TDB_DATA value;
     312             : 
     313           0 :         state->idx++;
     314             : 
     315           0 :         alias_sid = state->obj->cur->object.identifier->sid;
     316             : 
     317           0 :         value = dbwrap_record_get_value(rec);
     318           0 :         mem = dssync_parse_mem(value);
     319           0 :         if (mem == NULL) {
     320           0 :                 return -1;
     321             :         }
     322             : 
     323           0 :         member_sid = mem->cur->sid;
     324           0 :         member_dn = mem->cur->dn;
     325             : 
     326           0 :         mem->obj = dssync_search_obj_by_guid(pctx, pctx->all, &mem->cur->guid);
     327           0 :         if (mem->obj == NULL) {
     328           0 :                 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
     329             :                          dom_sid_str_buf(&alias_sid, &buf1),
     330             :                          is_null_sid(&member_sid)?
     331             :                          dom_sid_str_buf(&member_sid, &buf2):
     332             :                          member_dn));
     333           0 :                 return 0;
     334             :         }
     335             : 
     336           0 :         switch (mem->obj->type) {
     337           0 :         case ATYPE_DISTRIBUTION_LOCAL_GROUP:
     338             :         case ATYPE_DISTRIBUTION_GLOBAL_GROUP:
     339           0 :                 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
     340             :                           dom_sid_str_buf(&alias_sid, &buf1),
     341             :                           member_dn));
     342           0 :                 return 0;
     343           0 :         default:
     344           0 :                 break;
     345             :         }
     346             : 
     347           0 :         DEBUG(0,("alias[%s] member[%s]\n",
     348             :                  dom_sid_str_buf(&alias_sid, &buf1),
     349             :                  dom_sid_str_buf(&member_sid, &buf2)));
     350             : 
     351           0 :         status = pdb_enum_aliasmem(&alias_sid, talloc_tos(),
     352             :                                    &members, &num_members);
     353           0 :         if (!NT_STATUS_IS_OK(status)) {
     354           0 :                 DEBUG(0, ("Could not find current alias members %s - %s\n",
     355             :                           dom_sid_str_buf(&alias_sid, &buf1),
     356             :                           nt_errstr(status)));
     357           0 :                 return -1;
     358             :         }
     359             : 
     360           0 :         for (i=0; i < num_members; i++) {
     361           0 :                 bool match;
     362             : 
     363           0 :                 match = dom_sid_equal(&members[i], &member_sid);
     364           0 :                 if (match) {
     365           0 :                         is_member = true;
     366           0 :                         break;
     367             :                 }
     368             :         }
     369             : 
     370           0 :         status = NT_STATUS_OK;
     371           0 :         action = "none";
     372           0 :         if (!is_member && mem->active) {
     373           0 :                 action = "add";
     374           0 :                 pdb_add_aliasmem(&alias_sid, &member_sid);
     375           0 :         } else if (is_member && !mem->active) {
     376           0 :                 action = "delete";
     377           0 :                 pdb_del_aliasmem(&alias_sid, &member_sid);
     378             :         }
     379           0 :         if (!NT_STATUS_IS_OK(status)) {
     380           0 :                 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
     381             :                           action,
     382             :                           dom_sid_str_buf(&member_sid, &buf1),
     383             :                           dom_sid_str_buf(&alias_sid, &buf2),
     384             :                           nt_errstr(status)));
     385           0 :                 return -1;
     386             :         }
     387             : 
     388           0 :         return 0;
     389             : }
     390             : 
     391           0 : static int dssync_passdb_traverse_aliases(struct db_record *rec,
     392             :                                           void *private_data)
     393             : {
     394           0 :         struct dssync_passdb_traverse_aliases *state =
     395             :                 (struct dssync_passdb_traverse_aliases *)private_data;
     396           0 :         struct dssync_passdb *pctx =
     397           0 :                 talloc_get_type_abort(state->ctx->private_data,
     398             :                 struct dssync_passdb);
     399           0 :         struct dssync_passdb_traverse_amembers mstate;
     400           0 :         struct dssync_passdb_obj *obj;
     401           0 :         TDB_DATA value;
     402           0 :         NTSTATUS status;
     403             : 
     404           0 :         state->idx++;
     405           0 :         if (pctx->methods == NULL) {
     406           0 :                 return -1;
     407             :         }
     408             : 
     409           0 :         value = dbwrap_record_get_value(rec);
     410           0 :         obj = dssync_parse_obj(value);
     411           0 :         if (obj == NULL) {
     412           0 :                 return -1;
     413             :         }
     414             : 
     415           0 :         ZERO_STRUCT(mstate);
     416           0 :         mstate.ctx = state->ctx;
     417           0 :         mstate.name = "members";
     418           0 :         mstate.obj = obj;
     419           0 :         status = dbwrap_traverse_read(obj->members,
     420             :                                       dssync_passdb_traverse_amembers,
     421             :                                       &mstate, NULL);
     422           0 :         if (!NT_STATUS_IS_OK(status)) {
     423           0 :                 return -1;
     424             :         }
     425             : 
     426           0 :         return 0;
     427             : }
     428             : 
     429             : struct dssync_passdb_traverse_gmembers {
     430             :         struct dssync_context *ctx;
     431             :         struct dssync_passdb_obj *obj;
     432             :         const char *name;
     433             :         uint32_t idx;
     434             : };
     435             : 
     436             : struct dssync_passdb_traverse_groups {
     437             :         struct dssync_context *ctx;
     438             :         const char *name;
     439             :         uint32_t idx;
     440             : };
     441             : 
     442           0 : static int dssync_passdb_traverse_gmembers(struct db_record *rec,
     443             :                                            void *private_data)
     444             : {
     445           0 :         struct dssync_passdb_traverse_gmembers *state =
     446             :                 (struct dssync_passdb_traverse_gmembers *)private_data;
     447           0 :         struct dssync_passdb *pctx =
     448           0 :                 talloc_get_type_abort(state->ctx->private_data,
     449             :                 struct dssync_passdb);
     450           0 :         struct dssync_passdb_mem *mem;
     451           0 :         NTSTATUS status;
     452           0 :         char *nt_member = NULL;
     453           0 :         char **unix_members;
     454           0 :         struct dom_sid group_sid;
     455           0 :         struct dom_sid member_sid;
     456           0 :         struct dom_sid_buf buf1, buf2;
     457           0 :         struct samu *member = NULL;
     458           0 :         const char *member_dn = NULL;
     459           0 :         GROUP_MAP *map;
     460           0 :         struct group *grp;
     461           0 :         uint32_t rid;
     462           0 :         bool is_unix_member = false;
     463           0 :         TDB_DATA value;
     464             : 
     465           0 :         state->idx++;
     466             : 
     467           0 :         group_sid = state->obj->cur->object.identifier->sid;
     468             : 
     469           0 :         status = dom_sid_split_rid(talloc_tos(), &group_sid, NULL, &rid);
     470           0 :         if (!NT_STATUS_IS_OK(status)) {
     471           0 :                 return -1;
     472             :         }
     473             : 
     474           0 :         value = dbwrap_record_get_value(rec);
     475             : 
     476           0 :         mem = dssync_parse_mem(value);
     477           0 :         if (mem == NULL) {
     478           0 :                 return -1;
     479             :         }
     480             : 
     481           0 :         member_sid = mem->cur->sid;
     482           0 :         member_dn = mem->cur->dn;
     483             : 
     484           0 :         mem->obj = dssync_search_obj_by_guid(pctx, pctx->all, &mem->cur->guid);
     485           0 :         if (mem->obj == NULL) {
     486           0 :                 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
     487             :                          dom_sid_str_buf(&group_sid, &buf1),
     488             :                          is_null_sid(&member_sid)?
     489             :                          dom_sid_str_buf(&member_sid, &buf2):
     490             :                          member_dn));
     491           0 :                 return 0;
     492             :         }
     493             : 
     494           0 :         member_sid = mem->obj->cur->object.identifier->sid;
     495           0 :         member_dn = mem->obj->cur->object.identifier->dn;
     496             : 
     497           0 :         switch (mem->obj->type) {
     498           0 :         case ATYPE_SECURITY_LOCAL_GROUP:
     499             :         case ATYPE_SECURITY_GLOBAL_GROUP:
     500           0 :                 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
     501             :                           dom_sid_str_buf(&group_sid, &buf1),
     502             :                           dom_sid_str_buf(&member_sid, &buf2)));
     503           0 :                 return 0;
     504             : 
     505           0 :         case ATYPE_DISTRIBUTION_LOCAL_GROUP:
     506             :         case ATYPE_DISTRIBUTION_GLOBAL_GROUP:
     507           0 :                 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
     508             :                           dom_sid_str_buf(&group_sid, &buf1),
     509             :                           member_dn));
     510           0 :                 return 0;
     511           0 :         default:
     512           0 :                 break;
     513             :         }
     514             : 
     515           0 :         map = talloc_zero(NULL, GROUP_MAP);
     516           0 :         if (!map) {
     517           0 :                 return -1;
     518             :         }
     519             : 
     520           0 :         if (!get_domain_group_from_sid(group_sid, map)) {
     521           0 :                 DEBUG(0, ("Could not find global group %s\n",
     522             :                           dom_sid_str_buf(&group_sid, &buf1)));
     523             :                 //return NT_STATUS_NO_SUCH_GROUP;
     524           0 :                 TALLOC_FREE(map);
     525           0 :                 return -1;
     526             :         }
     527             : 
     528           0 :         if (!(grp = getgrgid(map->gid))) {
     529           0 :                 DEBUG(0, ("Could not find unix group %lu\n",
     530             :                                                 (unsigned long)map->gid));
     531             :                 //return NT_STATUS_NO_SUCH_GROUP;
     532           0 :                 TALLOC_FREE(map);
     533           0 :                 return -1;
     534             :         }
     535             : 
     536           0 :         TALLOC_FREE(map);
     537             : 
     538           0 :         DEBUG(0,("Group members of %s: ", grp->gr_name));
     539             : 
     540           0 :         if ( !(member = samu_new(talloc_tos())) ) {
     541             :                 //return NT_STATUS_NO_MEMORY;
     542           0 :                 return -1;
     543             :         }
     544             : 
     545           0 :         if (!pdb_getsampwsid(member, &member_sid)) {
     546           0 :                 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
     547             :                           dom_sid_str_buf(&member_sid, &buf1),
     548             :                           grp->gr_name));
     549           0 :                 TALLOC_FREE(member);
     550           0 :                 return -1;
     551             :         }
     552             : 
     553           0 :         if (pdb_get_group_rid(member) == rid) {
     554           0 :                 DEBUGADD(0,("%s(primary),", pdb_get_username(member)));
     555           0 :                 TALLOC_FREE(member);
     556           0 :                 return -1;
     557             :         }
     558             : 
     559           0 :         DEBUGADD(0,("%s,", pdb_get_username(member)));
     560           0 :         nt_member = talloc_strdup(talloc_tos(), pdb_get_username(member));
     561           0 :         TALLOC_FREE(member);
     562             : 
     563           0 :         DEBUGADD(0,("\n"));
     564             : 
     565           0 :         unix_members = grp->gr_mem;
     566             : 
     567           0 :         while (*unix_members) {
     568           0 :                 if (strcmp(*unix_members, nt_member) == 0) {
     569           0 :                         is_unix_member = true;
     570           0 :                         break;
     571             :                 }
     572           0 :                 unix_members += 1;
     573             :         }
     574             : 
     575           0 :         if (!is_unix_member && mem->active) {
     576           0 :                 smb_add_user_group(grp->gr_name, nt_member);
     577           0 :         } else if (is_unix_member && !mem->active) {
     578           0 :                 smb_delete_user_group(grp->gr_name, nt_member);
     579             :         }
     580             : 
     581           0 :         return 0;
     582             : }
     583             : 
     584           0 : static int dssync_passdb_traverse_groups(struct db_record *rec,
     585             :                                          void *private_data)
     586             : {
     587           0 :         struct dssync_passdb_traverse_groups *state =
     588             :                 (struct dssync_passdb_traverse_groups *)private_data;
     589           0 :         struct dssync_passdb *pctx =
     590           0 :                 talloc_get_type_abort(state->ctx->private_data,
     591             :                 struct dssync_passdb);
     592           0 :         struct dssync_passdb_traverse_gmembers mstate;
     593           0 :         struct dssync_passdb_obj *obj;
     594           0 :         TDB_DATA value;
     595           0 :         NTSTATUS status;
     596             : 
     597           0 :         state->idx++;
     598           0 :         if (pctx->methods == NULL) {
     599           0 :                 return -1;
     600             :         }
     601             : 
     602           0 :         value = dbwrap_record_get_value(rec);
     603             : 
     604           0 :         obj = dssync_parse_obj(value);
     605           0 :         if (obj == NULL) {
     606           0 :                 return -1;
     607             :         }
     608             : 
     609           0 :         ZERO_STRUCT(mstate);
     610           0 :         mstate.ctx = state->ctx;
     611           0 :         mstate.name = "members";
     612           0 :         mstate.obj = obj;
     613           0 :         status = dbwrap_traverse_read(obj->members,
     614             :                                       dssync_passdb_traverse_gmembers,
     615             :                                       &mstate, NULL);
     616           0 :         if (!NT_STATUS_IS_OK(status)) {
     617           0 :                 return -1;
     618             :         }
     619             : 
     620           0 :         return 0;
     621             : }
     622             : 
     623           0 : static NTSTATUS passdb_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
     624             :                               struct replUpToDateVectorBlob *new_utdv)
     625             : {
     626           0 :         struct dssync_passdb *pctx =
     627           0 :                 talloc_get_type_abort(ctx->private_data,
     628             :                 struct dssync_passdb);
     629           0 :         struct dssync_passdb_traverse_aliases astate;
     630           0 :         struct dssync_passdb_traverse_groups gstate;
     631           0 :         NTSTATUS status;
     632             : 
     633           0 :         ZERO_STRUCT(astate);
     634           0 :         astate.ctx = ctx;
     635           0 :         astate.name = "aliases";
     636           0 :         status = dbwrap_traverse_read(pctx->aliases,
     637             :                                       dssync_passdb_traverse_aliases,
     638             :                                       &astate, NULL);
     639           0 :         if (!NT_STATUS_IS_OK(status)) {
     640           0 :                 return NT_STATUS_INTERNAL_ERROR;
     641             :         }
     642             : 
     643           0 :         ZERO_STRUCT(gstate);
     644           0 :         gstate.ctx = ctx;
     645           0 :         gstate.name = "groups";
     646           0 :         status = dbwrap_traverse_read(pctx->groups,
     647             :                                       dssync_passdb_traverse_groups,
     648             :                                       &gstate, NULL);
     649           0 :         if (!NT_STATUS_IS_OK(status)) {
     650           0 :                 return NT_STATUS_INTERNAL_ERROR;
     651             :         }
     652             : 
     653           0 :         TALLOC_FREE(pctx->methods);
     654           0 :         TALLOC_FREE(pctx);
     655             : 
     656           0 :         return NT_STATUS_OK;
     657             : }
     658             : 
     659             : /****************************************************************
     660             : ****************************************************************/
     661             : 
     662           0 : static NTSTATUS smb_create_user(TALLOC_CTX *mem_ctx,
     663             :                                 uint32_t acct_flags,
     664             :                                 const char *account,
     665             :                                 struct passwd **passwd_p)
     666             : {
     667           0 :         const struct loadparm_substitution *lp_sub =
     668           0 :                 loadparm_s3_global_substitution();
     669           0 :         struct passwd *passwd;
     670           0 :         char *add_script = NULL;
     671             : 
     672           0 :         passwd = Get_Pwnam_alloc(mem_ctx, account);
     673           0 :         if (passwd) {
     674           0 :                 *passwd_p = passwd;
     675           0 :                 return NT_STATUS_OK;
     676             :         }
     677             : 
     678             :         /* Create appropriate user */
     679           0 :         if (acct_flags & ACB_NORMAL) {
     680           0 :                 add_script = lp_add_user_script(mem_ctx, lp_sub);
     681           0 :         } else if ( (acct_flags & ACB_WSTRUST) ||
     682           0 :                     (acct_flags & ACB_SVRTRUST) ||
     683           0 :                     (acct_flags & ACB_DOMTRUST) ) {
     684           0 :                 add_script = lp_add_machine_script(mem_ctx, lp_sub);
     685             :         } else {
     686           0 :                 DEBUG(1, ("Unknown user type: %s\n",
     687             :                           pdb_encode_acct_ctrl(acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
     688           0 :                 return NT_STATUS_UNSUCCESSFUL;
     689             :         }
     690             : 
     691           0 :         if (!add_script) {
     692           0 :                 return NT_STATUS_NO_MEMORY;
     693             :         }
     694             : 
     695           0 :         if (*add_script) {
     696           0 :                 int add_ret;
     697           0 :                 add_script = talloc_all_string_sub(mem_ctx, add_script,
     698             :                                                    "%u", account);
     699           0 :                 if (!add_script) {
     700           0 :                         return NT_STATUS_NO_MEMORY;
     701             :                 }
     702           0 :                 add_ret = smbrun(add_script, NULL, NULL);
     703           0 :                 DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
     704             :                          "gave %d\n", add_script, add_ret));
     705           0 :                 if (add_ret == 0) {
     706           0 :                         smb_nscd_flush_user_cache();
     707             :                 }
     708             :         }
     709             : 
     710             :         /* try and find the possible unix account again */
     711           0 :         passwd = Get_Pwnam_alloc(mem_ctx, account);
     712           0 :         if (!passwd) {
     713           0 :                 return NT_STATUS_NO_SUCH_USER;
     714             :         }
     715             : 
     716           0 :         *passwd_p = passwd;
     717             : 
     718           0 :         return NT_STATUS_OK;
     719             : }
     720             : 
     721           0 : static struct drsuapi_DsReplicaAttribute *find_drsuapi_attr(
     722             :                         const struct drsuapi_DsReplicaObjectListItemEx *cur,
     723             :                         uint32_t attid)
     724             : {
     725           0 :         uint32_t i = 0;
     726             : 
     727           0 :         for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
     728           0 :                 struct drsuapi_DsReplicaAttribute *attr;
     729             : 
     730           0 :                 attr = &cur->object.attribute_ctr.attributes[i];
     731             : 
     732           0 :                 if (attr->attid == attid) {
     733           0 :                         return attr;
     734             :                 }
     735             :         }
     736             : 
     737           0 :         return NULL;
     738             : }
     739             : 
     740           0 : static NTSTATUS find_drsuapi_attr_string(TALLOC_CTX *mem_ctx,
     741             :                                          const struct drsuapi_DsReplicaObjectListItemEx *cur,
     742             :                                          uint32_t attid,
     743             :                                          uint32_t *_count,
     744             :                                          char ***_array)
     745             : {
     746           0 :         struct drsuapi_DsReplicaAttribute *attr;
     747           0 :         char **array;
     748           0 :         uint32_t a;
     749             : 
     750           0 :         attr = find_drsuapi_attr(cur, attid);
     751           0 :         if (attr == NULL) {
     752           0 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     753             :         }
     754             : 
     755           0 :         array = talloc_array(mem_ctx, char *, attr->value_ctr.num_values);
     756           0 :         if (array == NULL) {
     757           0 :                 return NT_STATUS_NO_MEMORY;
     758             :         }
     759             : 
     760           0 :         for (a = 0; a < attr->value_ctr.num_values; a++) {
     761           0 :                 const DATA_BLOB *blob;
     762           0 :                 ssize_t ret;
     763             : 
     764           0 :                 blob = attr->value_ctr.values[a].blob;
     765             : 
     766           0 :                 if (blob == NULL) {
     767           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     768             :                 }
     769             : 
     770           0 :                 ret = pull_string_talloc(array, NULL, 0, &array[a],
     771           0 :                                          blob->data, blob->length,
     772             :                                          STR_UNICODE);
     773           0 :                 if (ret == -1) {
     774             :                         //TODO
     775           0 :                         return NT_STATUS_INTERNAL_ERROR;
     776             :                 }
     777             :         }
     778             : 
     779           0 :         *_count = attr->value_ctr.num_values;
     780           0 :         *_array = array;
     781           0 :         return NT_STATUS_OK;
     782             : }
     783             : 
     784           0 : static NTSTATUS find_drsuapi_attr_int32(TALLOC_CTX *mem_ctx,
     785             :                                         const struct drsuapi_DsReplicaObjectListItemEx *cur,
     786             :                                         uint32_t attid,
     787             :                                         uint32_t *_count,
     788             :                                         int32_t **_array)
     789             : {
     790           0 :         struct drsuapi_DsReplicaAttribute *attr;
     791           0 :         int32_t *array;
     792           0 :         uint32_t a;
     793             : 
     794           0 :         attr = find_drsuapi_attr(cur, attid);
     795           0 :         if (attr == NULL) {
     796           0 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     797             :         }
     798             : 
     799           0 :         array = talloc_array(mem_ctx, int32_t, attr->value_ctr.num_values);
     800           0 :         if (array == NULL) {
     801           0 :                 return NT_STATUS_NO_MEMORY;
     802             :         }
     803             : 
     804           0 :         for (a = 0; a < attr->value_ctr.num_values; a++) {
     805           0 :                 const DATA_BLOB *blob;
     806             : 
     807           0 :                 blob = attr->value_ctr.values[a].blob;
     808             : 
     809           0 :                 if (blob == NULL) {
     810           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     811             :                 }
     812             : 
     813           0 :                 if (blob->length != 4) {
     814           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     815             :                 }
     816             : 
     817           0 :                 array[a] = IVAL(blob->data, 0);
     818             :         }
     819             : 
     820           0 :         *_count = attr->value_ctr.num_values;
     821           0 :         *_array = array;
     822           0 :         return NT_STATUS_OK;
     823             : }
     824             : 
     825           0 : static NTSTATUS find_drsuapi_attr_blob(TALLOC_CTX *mem_ctx,
     826             :                                        const struct drsuapi_DsReplicaObjectListItemEx *cur,
     827             :                                        uint32_t attid,
     828             :                                        uint32_t *_count,
     829             :                                        DATA_BLOB **_array)
     830             : {
     831           0 :         struct drsuapi_DsReplicaAttribute *attr;
     832           0 :         DATA_BLOB *array;
     833           0 :         uint32_t a;
     834             : 
     835           0 :         attr = find_drsuapi_attr(cur, attid);
     836           0 :         if (attr == NULL) {
     837           0 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     838             :         }
     839             : 
     840           0 :         array = talloc_array(mem_ctx, DATA_BLOB, attr->value_ctr.num_values);
     841           0 :         if (array == NULL) {
     842           0 :                 return NT_STATUS_NO_MEMORY;
     843             :         }
     844             : 
     845           0 :         for (a = 0; a < attr->value_ctr.num_values; a++) {
     846           0 :                 const DATA_BLOB *blob;
     847             : 
     848           0 :                 blob = attr->value_ctr.values[a].blob;
     849             : 
     850           0 :                 if (blob == NULL) {
     851           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     852             :                 }
     853             : 
     854           0 :                 array[a] = data_blob_talloc(array, blob->data, blob->length);
     855           0 :                 if (array[a].length != blob->length) {
     856           0 :                         return NT_STATUS_NO_MEMORY;
     857             :                 }
     858             :         }
     859           0 :         *_count = attr->value_ctr.num_values;
     860           0 :         *_array = array;
     861           0 :         return NT_STATUS_OK;
     862             : }
     863             : 
     864           0 : static NTSTATUS find_drsuapi_attr_int64(TALLOC_CTX *mem_ctx,
     865             :                                         const struct drsuapi_DsReplicaObjectListItemEx *cur,
     866             :                                         uint32_t attid,
     867             :                                         uint32_t *_count,
     868             :                                         int64_t **_array)
     869             : {
     870           0 :         struct drsuapi_DsReplicaAttribute *attr;
     871           0 :         int64_t *array;
     872           0 :         uint32_t a;
     873             : 
     874           0 :         attr = find_drsuapi_attr(cur, attid);
     875           0 :         if (attr == NULL) {
     876           0 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     877             :         }
     878             : 
     879           0 :         array = talloc_array(mem_ctx, int64_t, attr->value_ctr.num_values);
     880           0 :         if (array == NULL) {
     881           0 :                 return NT_STATUS_NO_MEMORY;
     882             :         }
     883             : 
     884           0 :         for (a = 0; a < attr->value_ctr.num_values; a++) {
     885           0 :                 const DATA_BLOB *blob;
     886             : 
     887           0 :                 blob = attr->value_ctr.values[a].blob;
     888             : 
     889           0 :                 if (blob == NULL) {
     890           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     891             :                 }
     892             : 
     893           0 :                 if (blob->length != 8) {
     894           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     895             :                 }
     896             : 
     897           0 :                 array[a] = BVAL(blob->data, 0);
     898             :         }
     899           0 :         *_count = attr->value_ctr.num_values;
     900           0 :         *_array = array;
     901           0 :         return NT_STATUS_OK;
     902             : }
     903             : 
     904           0 : static NTSTATUS find_drsuapi_attr_dn(TALLOC_CTX *mem_ctx,
     905             :                                      const struct drsuapi_DsReplicaObjectListItemEx *cur,
     906             :                                      uint32_t attid,
     907             :                                      uint32_t *_count,
     908             :                                      struct drsuapi_DsReplicaObjectIdentifier3 **_array)
     909             : {
     910           0 :         struct drsuapi_DsReplicaAttribute *attr;
     911           0 :         struct drsuapi_DsReplicaObjectIdentifier3 *array;
     912           0 :         uint32_t a;
     913             : 
     914           0 :         attr = find_drsuapi_attr(cur, attid);
     915           0 :         if (attr == NULL) {
     916           0 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     917             :         }
     918             : 
     919           0 :         array = talloc_array(mem_ctx,
     920             :                              struct drsuapi_DsReplicaObjectIdentifier3,
     921             :                              attr->value_ctr.num_values);
     922           0 :         if (array == NULL) {
     923           0 :                 return NT_STATUS_NO_MEMORY;
     924             :         }
     925             : 
     926           0 :         for (a = 0; a < attr->value_ctr.num_values; a++) {
     927           0 :                 const DATA_BLOB *blob;
     928           0 :                 enum ndr_err_code ndr_err;
     929           0 :                 NTSTATUS status;
     930             : 
     931           0 :                 blob = attr->value_ctr.values[a].blob;
     932             : 
     933           0 :                 if (blob == NULL) {
     934           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     935             :                 }
     936             : 
     937             :                 /* windows sometimes sends an extra two pad bytes here */
     938           0 :                 ndr_err = ndr_pull_struct_blob(blob, array, &array[a],
     939             :                                 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
     940           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     941           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     942           0 :                         return status;
     943             :                 }
     944             :         }
     945           0 :         *_count = attr->value_ctr.num_values;
     946           0 :         *_array = array;
     947           0 :         return NT_STATUS_OK;
     948             : }
     949             : 
     950             : #define GET_BLOB_EX(attr, needed) do { \
     951             :         NTSTATUS _status; \
     952             :         uint32_t _cnt; \
     953             :         DATA_BLOB *_vals = NULL; \
     954             :         attr = data_blob_null; \
     955             :         _status = find_drsuapi_attr_blob(mem_ctx, cur, \
     956             :                                          DRSUAPI_ATTID_ ## attr, \
     957             :                                          &_cnt, &_vals); \
     958             :         if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
     959             :                 if (!needed) { \
     960             :                         _status = NT_STATUS_OK; \
     961             :                         _cnt = 0; \
     962             :                 } \
     963             :         } \
     964             :         if (!NT_STATUS_IS_OK(_status)) { \
     965             :                 DEBUG(0,(__location__ "attr[%s] %s\n", \
     966             :                         #attr, nt_errstr(_status))); \
     967             :                 return _status; \
     968             :         } \
     969             :         if (_cnt == 0) { \
     970             :                 if (needed) { \
     971             :                         talloc_free(_vals); \
     972             :                         DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
     973             :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
     974             :                 } \
     975             :         } else if (_cnt > 1) { \
     976             :                 talloc_free(_vals); \
     977             :                 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
     978             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
     979             :         } else { \
     980             :                 attr = _vals[0]; \
     981             :                 (void)talloc_steal(mem_ctx, _vals[0].data); \
     982             :         } \
     983             :         talloc_free(_vals); \
     984             : } while(0)
     985             : 
     986             : #define GET_STRING_EX(attr, needed) do { \
     987             :         NTSTATUS _status; \
     988             :         uint32_t _cnt; \
     989             :         char **_vals = NULL; \
     990             :         attr = NULL; \
     991             :         _status = find_drsuapi_attr_string(mem_ctx, cur, \
     992             :                                            DRSUAPI_ATTID_ ## attr, \
     993             :                                            &_cnt, &_vals); \
     994             :         if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
     995             :                 if (!needed) { \
     996             :                         _status = NT_STATUS_OK; \
     997             :                         _cnt = 0; \
     998             :                 } \
     999             :         } \
    1000             :         if (!NT_STATUS_IS_OK(_status)) { \
    1001             :                 DEBUG(0,(__location__ "attr[%s] %s\n", \
    1002             :                         #attr, nt_errstr(_status))); \
    1003             :                 return _status; \
    1004             :         } \
    1005             :         if (_cnt == 0) { \
    1006             :                 if (needed) { \
    1007             :                         talloc_free(_vals); \
    1008             :                         DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1009             :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
    1010             :                 } \
    1011             :         } else if (_cnt > 1) { \
    1012             :                 talloc_free(_vals); \
    1013             :                 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1014             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
    1015             :         } else { \
    1016             :                 attr = talloc_move(mem_ctx, &_vals[0]); \
    1017             :         } \
    1018             :         talloc_free(_vals); \
    1019             : } while(0)
    1020             : 
    1021             : #define GET_UINT32_EX(attr, needed) do { \
    1022             :         NTSTATUS _status; \
    1023             :         uint32_t _cnt; \
    1024             :         int32_t*_vals = NULL; \
    1025             :         attr = 0; \
    1026             :         _status = find_drsuapi_attr_int32(mem_ctx, cur, \
    1027             :                                           DRSUAPI_ATTID_ ## attr, \
    1028             :                                           &_cnt, &_vals); \
    1029             :         if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
    1030             :                 if (!needed) { \
    1031             :                         _status = NT_STATUS_OK; \
    1032             :                         _cnt = 0; \
    1033             :                 } \
    1034             :         } \
    1035             :         if (!NT_STATUS_IS_OK(_status)) { \
    1036             :                 DEBUG(0,(__location__ "attr[%s] %s\n", \
    1037             :                         #attr, nt_errstr(_status))); \
    1038             :                 return _status; \
    1039             :         } \
    1040             :         if (_cnt == 0) { \
    1041             :                 if (needed) { \
    1042             :                         talloc_free(_vals); \
    1043             :                         DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1044             :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
    1045             :                 } \
    1046             :         } else if (_cnt > 1) { \
    1047             :                 talloc_free(_vals); \
    1048             :                 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1049             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
    1050             :         } else { \
    1051             :                 attr = (uint32_t)_vals[0]; \
    1052             :         } \
    1053             :         talloc_free(_vals); \
    1054             : } while(0)
    1055             : 
    1056             : #define GET_UINT64_EX(attr, needed) do { \
    1057             :         NTSTATUS _status; \
    1058             :         uint32_t _cnt; \
    1059             :         int64_t *_vals = NULL; \
    1060             :         attr = 0; \
    1061             :         _status = find_drsuapi_attr_int64(mem_ctx, cur, \
    1062             :                                           DRSUAPI_ATTID_ ## attr, \
    1063             :                                           &_cnt, &_vals); \
    1064             :         if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
    1065             :                 if (!needed) { \
    1066             :                         _status = NT_STATUS_OK; \
    1067             :                         _cnt = 0; \
    1068             :                 } \
    1069             :         } \
    1070             :         if (!NT_STATUS_IS_OK(_status)) { \
    1071             :                 DEBUG(0,(__location__ "attr[%s] %s\n", \
    1072             :                         #attr, nt_errstr(_status))); \
    1073             :                 return _status; \
    1074             :         } \
    1075             :         if (_cnt == 0) { \
    1076             :                 if (needed) { \
    1077             :                         talloc_free(_vals); \
    1078             :                         DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1079             :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
    1080             :                 } \
    1081             :         } else if (_cnt > 1) { \
    1082             :                 talloc_free(_vals); \
    1083             :                 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
    1084             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
    1085             :         } else { \
    1086             :                 attr = (uint64_t)_vals[0]; \
    1087             :         } \
    1088             :         talloc_free(_vals); \
    1089             : } while(0)
    1090             : 
    1091             : #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
    1092             : #define GET_STRING(attr) GET_STRING_EX(attr, false)
    1093             : #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
    1094             : #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
    1095             : 
    1096             : /* Convert a struct samu_DELTA to a struct samu. */
    1097             : #define STRING_CHANGED (old_string && !new_string) ||\
    1098             :                     (!old_string && new_string) ||\
    1099             :                 (old_string && new_string && (strcmp(old_string, new_string) != 0))
    1100             : 
    1101             : #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
    1102             :                     (!(s1) && (s2)) ||\
    1103             :                 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
    1104             : 
    1105             : /****************************************************************
    1106             : ****************************************************************/
    1107             : 
    1108           0 : static NTSTATUS sam_account_from_object(struct samu *account,
    1109             :                                 struct drsuapi_DsReplicaObjectListItemEx *cur)
    1110             : {
    1111           0 :         TALLOC_CTX *mem_ctx = account;
    1112           0 :         const char *old_string, *new_string;
    1113           0 :         struct dom_sid_buf buf;
    1114           0 :         time_t unix_time, stored_time;
    1115           0 :         NTSTATUS status;
    1116             : 
    1117           0 :         NTTIME lastLogon;
    1118           0 :         NTTIME lastLogoff;
    1119           0 :         NTTIME pwdLastSet;
    1120           0 :         NTTIME accountExpires;
    1121           0 :         const char *sAMAccountName;
    1122           0 :         const char *displayName;
    1123           0 :         const char *homeDirectory;
    1124           0 :         const char *homeDrive;
    1125           0 :         const char *scriptPath;
    1126           0 :         const char *profilePath;
    1127           0 :         const char *description;
    1128           0 :         const char *userWorkstations;
    1129           0 :         DATA_BLOB userParameters;
    1130           0 :         struct dom_sid objectSid;
    1131           0 :         uint32_t primaryGroupID;
    1132           0 :         uint32_t userAccountControl;
    1133           0 :         DATA_BLOB logonHours;
    1134           0 :         uint32_t badPwdCount;
    1135           0 :         uint32_t logonCount;
    1136           0 :         DATA_BLOB unicodePwd;
    1137           0 :         DATA_BLOB dBCSPwd;
    1138             : 
    1139           0 :         uint32_t rid = 0;
    1140           0 :         uint32_t acct_flags;
    1141           0 :         uint32_t units_per_week;
    1142             : 
    1143           0 :         objectSid = cur->object.identifier->sid;
    1144           0 :         GET_STRING_EX(sAMAccountName, true);
    1145           0 :         DEBUG(0,("sam_account_from_object(%s, %s) start\n",
    1146             :                  sAMAccountName,
    1147             :                  dom_sid_str_buf(&objectSid, &buf)));
    1148           0 :         GET_UINT64(lastLogon);
    1149           0 :         GET_UINT64(lastLogoff);
    1150           0 :         GET_UINT64(pwdLastSet);
    1151           0 :         GET_UINT64(accountExpires);
    1152           0 :         GET_STRING(displayName);
    1153           0 :         GET_STRING(homeDirectory);
    1154           0 :         GET_STRING(homeDrive);
    1155           0 :         GET_STRING(scriptPath);
    1156           0 :         GET_STRING(profilePath);
    1157           0 :         GET_STRING(description);
    1158           0 :         GET_STRING(userWorkstations);
    1159           0 :         GET_BLOB(userParameters);
    1160           0 :         GET_UINT32(primaryGroupID);
    1161           0 :         GET_UINT32(userAccountControl);
    1162           0 :         GET_BLOB(logonHours);
    1163           0 :         GET_UINT32(badPwdCount);
    1164           0 :         GET_UINT32(logonCount);
    1165           0 :         GET_BLOB(unicodePwd);
    1166           0 :         GET_BLOB(dBCSPwd);
    1167             : 
    1168           0 :         status = dom_sid_split_rid(mem_ctx, &objectSid, NULL, &rid);
    1169           0 :         if (!NT_STATUS_IS_OK(status)) {
    1170           0 :                 return status;
    1171             :         }
    1172           0 :         acct_flags = ds_uf2acb(userAccountControl);
    1173             : 
    1174             :         /* Username, fullname, home dir, dir drive, logon script, acct
    1175             :            desc, workstations, profile. */
    1176             : 
    1177           0 :         if (sAMAccountName) {
    1178           0 :                 old_string = pdb_get_nt_username(account);
    1179           0 :                 new_string = sAMAccountName;
    1180             : 
    1181           0 :                 if (STRING_CHANGED) {
    1182           0 :                         pdb_set_nt_username(account, new_string, PDB_CHANGED);
    1183             :                 }
    1184             : 
    1185             :                 /* Unix username is the same - for sanity */
    1186           0 :                 old_string = pdb_get_username( account );
    1187           0 :                 if (STRING_CHANGED) {
    1188           0 :                         pdb_set_username(account, new_string, PDB_CHANGED);
    1189             :                 }
    1190             :         }
    1191             : 
    1192           0 :         if (displayName) {
    1193           0 :                 old_string = pdb_get_fullname(account);
    1194           0 :                 new_string = displayName;
    1195             : 
    1196           0 :                 if (STRING_CHANGED)
    1197           0 :                         pdb_set_fullname(account, new_string, PDB_CHANGED);
    1198             :         }
    1199             : 
    1200           0 :         if (homeDirectory) {
    1201           0 :                 old_string = pdb_get_homedir(account);
    1202           0 :                 new_string = homeDirectory;
    1203             : 
    1204           0 :                 if (STRING_CHANGED)
    1205           0 :                         pdb_set_homedir(account, new_string, PDB_CHANGED);
    1206             :         }
    1207             : 
    1208           0 :         if (homeDrive) {
    1209           0 :                 old_string = pdb_get_dir_drive(account);
    1210           0 :                 new_string = homeDrive;
    1211             : 
    1212           0 :                 if (STRING_CHANGED)
    1213           0 :                         pdb_set_dir_drive(account, new_string, PDB_CHANGED);
    1214             :         }
    1215             : 
    1216           0 :         if (scriptPath) {
    1217           0 :                 old_string = pdb_get_logon_script(account);
    1218           0 :                 new_string = scriptPath;
    1219             : 
    1220           0 :                 if (STRING_CHANGED)
    1221           0 :                         pdb_set_logon_script(account, new_string, PDB_CHANGED);
    1222             :         }
    1223             : 
    1224           0 :         if (description) {
    1225           0 :                 old_string = pdb_get_acct_desc(account);
    1226           0 :                 new_string = description;
    1227             : 
    1228           0 :                 if (STRING_CHANGED)
    1229           0 :                         pdb_set_acct_desc(account, new_string, PDB_CHANGED);
    1230             :         }
    1231             : 
    1232           0 :         if (userWorkstations) {
    1233           0 :                 old_string = pdb_get_workstations(account);
    1234           0 :                 new_string = userWorkstations;
    1235             : 
    1236           0 :                 if (STRING_CHANGED)
    1237           0 :                         pdb_set_workstations(account, new_string, PDB_CHANGED);
    1238             :         }
    1239             : 
    1240           0 :         if (profilePath) {
    1241           0 :                 old_string = pdb_get_profile_path(account);
    1242           0 :                 new_string = profilePath;
    1243             : 
    1244           0 :                 if (STRING_CHANGED)
    1245           0 :                         pdb_set_profile_path(account, new_string, PDB_CHANGED);
    1246             :         }
    1247             : 
    1248           0 :         if (userParameters.data) {
    1249           0 :                 char *newstr = NULL;
    1250           0 :                 old_string = pdb_get_munged_dial(account);
    1251             : 
    1252           0 :                 if (userParameters.length != 0) {
    1253           0 :                         newstr = base64_encode_data_blob(talloc_tos(),
    1254             :                                                          userParameters);
    1255           0 :                         SMB_ASSERT(newstr != NULL);
    1256             :                 }
    1257             : 
    1258           0 :                 if (STRING_CHANGED_NC(old_string, newstr))
    1259           0 :                         pdb_set_munged_dial(account, newstr, PDB_CHANGED);
    1260           0 :                 TALLOC_FREE(newstr);
    1261             :         }
    1262             : 
    1263             :         /* User and group sid */
    1264           0 :         if (rid != 0 && pdb_get_user_rid(account) != rid) {
    1265           0 :                 pdb_set_user_sid_from_rid(account, rid, PDB_CHANGED);
    1266             :         }
    1267           0 :         if (primaryGroupID != 0 && pdb_get_group_rid(account) != primaryGroupID) {
    1268           0 :                 pdb_set_group_sid_from_rid(account, primaryGroupID, PDB_CHANGED);
    1269             :         }
    1270             : 
    1271             :         /* Logon and password information */
    1272           0 :         if (!nt_time_is_zero(&lastLogon)) {
    1273           0 :                 unix_time = nt_time_to_unix(lastLogon);
    1274           0 :                 stored_time = pdb_get_logon_time(account);
    1275           0 :                 if (stored_time != unix_time)
    1276           0 :                         pdb_set_logon_time(account, unix_time, PDB_CHANGED);
    1277             :         }
    1278             : 
    1279           0 :         if (!nt_time_is_zero(&lastLogoff)) {
    1280           0 :                 unix_time = nt_time_to_unix(lastLogoff);
    1281           0 :                 stored_time = pdb_get_logoff_time(account);
    1282           0 :                 if (stored_time != unix_time)
    1283           0 :                         pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
    1284             :         }
    1285             : 
    1286             :         /* Logon Divs */
    1287           0 :         units_per_week = logonHours.length * 8;
    1288             : 
    1289           0 :         if (pdb_get_logon_divs(account) != units_per_week) {
    1290           0 :                 pdb_set_logon_divs(account, units_per_week, PDB_CHANGED);
    1291             :         }
    1292             : 
    1293             :         /* Logon Hours Len */
    1294           0 :         if (units_per_week/8 != pdb_get_hours_len(account)) {
    1295           0 :                 pdb_set_hours_len(account, units_per_week/8, PDB_CHANGED);
    1296             :         }
    1297             : 
    1298             :         /* Logon Hours */
    1299           0 :         if (logonHours.data) {
    1300           0 :                 char oldstr[44], newstr[44];
    1301           0 :                 pdb_sethexhours(oldstr, pdb_get_hours(account));
    1302           0 :                 pdb_sethexhours(newstr, logonHours.data);
    1303           0 :                 if (!strequal(oldstr, newstr)) {
    1304           0 :                         pdb_set_hours(account, logonHours.data,
    1305           0 :                                       logonHours.length, PDB_CHANGED);
    1306             :                 }
    1307             :         }
    1308             : 
    1309           0 :         if (pdb_get_bad_password_count(account) != badPwdCount)
    1310           0 :                 pdb_set_bad_password_count(account, badPwdCount, PDB_CHANGED);
    1311             : 
    1312           0 :         if (pdb_get_logon_count(account) != logonCount)
    1313           0 :                 pdb_set_logon_count(account, logonCount, PDB_CHANGED);
    1314             : 
    1315           0 :         if (!nt_time_is_zero(&pwdLastSet)) {
    1316           0 :                 unix_time = nt_time_to_unix(pwdLastSet);
    1317           0 :                 stored_time = pdb_get_pass_last_set_time(account);
    1318           0 :                 if (stored_time != unix_time)
    1319           0 :                         pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
    1320             :         } else {
    1321             :                 /* no last set time, make it now */
    1322           0 :                 pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED);
    1323             :         }
    1324             : 
    1325           0 :         if (!nt_time_is_zero(&accountExpires)) {
    1326           0 :                 unix_time = nt_time_to_unix(accountExpires);
    1327           0 :                 stored_time = pdb_get_kickoff_time(account);
    1328           0 :                 if (stored_time != unix_time)
    1329           0 :                         pdb_set_kickoff_time(account, unix_time, PDB_CHANGED);
    1330             :         }
    1331             : 
    1332             :         /* Decode hashes from password hash
    1333             :            Note that win2000 may send us all zeros for the hashes if it doesn't
    1334             :            think this channel is secure enough - don't set the passwords at all
    1335             :            in that case
    1336             :         */
    1337           0 :         if (dBCSPwd.length == 16 && !all_zero(dBCSPwd.data, 16)) {
    1338           0 :                 pdb_set_lanman_passwd(account, dBCSPwd.data, PDB_CHANGED);
    1339             :         }
    1340             : 
    1341           0 :         if (unicodePwd.length == 16 && !all_zero(unicodePwd.data, 16)) {
    1342           0 :                 pdb_set_nt_passwd(account, unicodePwd.data, PDB_CHANGED);
    1343             :         }
    1344             : 
    1345             :         /* TODO: history */
    1346             : 
    1347             :         /* TODO: account expiry time */
    1348             : 
    1349           0 :         pdb_set_acct_ctrl(account, acct_flags, PDB_CHANGED);
    1350             : 
    1351           0 :         pdb_set_domain(account, lp_workgroup(), PDB_CHANGED);
    1352             : 
    1353           0 :         DEBUG(0,("sam_account_from_object(%s, %s) done\n",
    1354             :                  sAMAccountName,
    1355             :                  dom_sid_str_buf(&objectSid, &buf)));
    1356           0 :         return NT_STATUS_OK;
    1357             : }
    1358             : 
    1359             : /****************************************************************
    1360             : ****************************************************************/
    1361             : 
    1362           0 : static NTSTATUS handle_account_object(struct dssync_passdb *pctx,
    1363             :                                       TALLOC_CTX *mem_ctx,
    1364             :                                       struct dssync_passdb_obj *obj)
    1365             : {
    1366           0 :         struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
    1367           0 :         NTSTATUS status;
    1368           0 :         fstring account;
    1369           0 :         struct samu *sam_account=NULL;
    1370           0 :         GROUP_MAP *map;
    1371           0 :         struct group *grp;
    1372           0 :         struct dom_sid user_sid;
    1373           0 :         struct dom_sid group_sid;
    1374           0 :         struct dom_sid_buf buf;
    1375           0 :         struct passwd *passwd = NULL;
    1376           0 :         uint32_t acct_flags;
    1377           0 :         uint32_t rid;
    1378             : 
    1379           0 :         const char *sAMAccountName;
    1380           0 :         uint32_t userAccountControl;
    1381             : 
    1382           0 :         user_sid = cur->object.identifier->sid;
    1383           0 :         GET_STRING_EX(sAMAccountName, true);
    1384           0 :         GET_UINT32_EX(userAccountControl, true);
    1385             : 
    1386           0 :         status = dom_sid_split_rid(mem_ctx, &user_sid, NULL, &rid);
    1387           0 :         if (!NT_STATUS_IS_OK(status)) {
    1388           0 :                 return status;
    1389             :         }
    1390             : 
    1391           0 :         fstrcpy(account, sAMAccountName);
    1392           0 :         if (rid == DOMAIN_RID_GUEST) {
    1393             :                 /*
    1394             :                  * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
    1395             :                  * that's why we need to ignore it here.
    1396             :                  *
    1397             :                  * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
    1398             :                  * code...
    1399             :                  */
    1400           0 :                 DEBUG(0,("Ignore %s - %s\n",
    1401             :                          account,
    1402             :                          dom_sid_str_buf(&user_sid, &buf)));
    1403           0 :                 return NT_STATUS_OK;
    1404             :         }
    1405           0 :         DEBUG(0,("Creating account: %s\n", account));
    1406             : 
    1407           0 :         if ( !(sam_account = samu_new(mem_ctx)) ) {
    1408           0 :                 return NT_STATUS_NO_MEMORY;
    1409             :         }
    1410             : 
    1411           0 :         acct_flags = ds_uf2acb(userAccountControl);
    1412           0 :         status = smb_create_user(sam_account, acct_flags, account, &passwd);
    1413           0 :         if (!NT_STATUS_IS_OK(status)) {
    1414           0 :                 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
    1415             :                         account, nt_errstr(status)));
    1416           0 :                 TALLOC_FREE(sam_account);
    1417           0 :                 return status;
    1418             :         }
    1419             : 
    1420           0 :         DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
    1421             :                   dom_sid_str_buf(&user_sid, &buf),
    1422             :                   account));
    1423           0 :         if (!pdb_getsampwsid(sam_account, &user_sid)) {
    1424           0 :                 sam_account_from_object(sam_account, cur);
    1425           0 :                 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
    1426             :                           dom_sid_str_buf(&user_sid, &buf),
    1427             :                           pdb_get_username(sam_account)));
    1428           0 :                 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account))) {
    1429           0 :                         DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
    1430             :                                   account));
    1431           0 :                         TALLOC_FREE(sam_account);
    1432           0 :                         return NT_STATUS_ACCESS_DENIED;
    1433             :                 }
    1434             :         } else {
    1435           0 :                 sam_account_from_object(sam_account, cur);
    1436           0 :                 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
    1437             :                           dom_sid_str_buf(&user_sid, &buf),
    1438             :                           pdb_get_username(sam_account)));
    1439           0 :                 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account))) {
    1440           0 :                         DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
    1441             :                                   account));
    1442           0 :                         TALLOC_FREE(sam_account);
    1443           0 :                         return NT_STATUS_ACCESS_DENIED;
    1444             :                 }
    1445             :         }
    1446             : 
    1447           0 :         if (pdb_get_group_sid(sam_account) == NULL) {
    1448           0 :                 TALLOC_FREE(sam_account);
    1449           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1450             :         }
    1451             : 
    1452           0 :         group_sid = *pdb_get_group_sid(sam_account);
    1453             : 
    1454           0 :         map = talloc_zero(NULL, GROUP_MAP);
    1455           0 :         if (!map) {
    1456           0 :                 return NT_STATUS_NO_MEMORY;
    1457             :         }
    1458             : 
    1459           0 :         if (!pdb_getgrsid(map, group_sid)) {
    1460           0 :                 DEBUG(0, ("Primary group of %s has no mapping!\n",
    1461             :                           pdb_get_username(sam_account)));
    1462             :         } else {
    1463           0 :                 if (map->gid != passwd->pw_gid) {
    1464           0 :                         if (!(grp = getgrgid(map->gid))) {
    1465           0 :                                 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
    1466             :                                           (unsigned long)map->gid, pdb_get_username(sam_account),
    1467             :                                           dom_sid_str_buf(&group_sid, &buf)));
    1468             :                         } else {
    1469           0 :                                 smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
    1470             :                         }
    1471             :                 }
    1472             :         }
    1473             : 
    1474           0 :         TALLOC_FREE(map);
    1475             : 
    1476           0 :         if ( !passwd ) {
    1477           0 :                 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
    1478             :                         pdb_get_username(sam_account)));
    1479             :         }
    1480             : 
    1481           0 :         TALLOC_FREE(sam_account);
    1482           0 :         return NT_STATUS_OK;
    1483             : }
    1484             : 
    1485             : /****************************************************************
    1486             : ****************************************************************/
    1487             : 
    1488           0 : static NTSTATUS handle_alias_object(struct dssync_passdb *pctx,
    1489             :                                     TALLOC_CTX *mem_ctx,
    1490             :                                     struct dssync_passdb_obj *obj)
    1491             : {
    1492           0 :         struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
    1493           0 :         NTSTATUS status;
    1494           0 :         struct group *grp = NULL;
    1495           0 :         struct dom_sid group_sid;
    1496           0 :         uint32_t rid = 0;
    1497           0 :         struct dom_sid *dom_sid = NULL;
    1498           0 :         struct dom_sid_buf sid_str;
    1499           0 :         GROUP_MAP *map;
    1500           0 :         bool insert = true;
    1501             : 
    1502           0 :         const char *sAMAccountName;
    1503           0 :         const char *description;
    1504           0 :         uint32_t i;
    1505           0 :         uint32_t num_members = 0;
    1506           0 :         struct drsuapi_DsReplicaObjectIdentifier3 *members = NULL;
    1507             : 
    1508           0 :         group_sid = cur->object.identifier->sid;
    1509           0 :         GET_STRING_EX(sAMAccountName, true);
    1510           0 :         GET_STRING(description);
    1511             : 
    1512           0 :         status = find_drsuapi_attr_dn(obj, cur, DRSUAPI_ATTID_member,
    1513             :                                       &num_members, &members);
    1514           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_PROPSET_NOT_FOUND)) {
    1515           0 :                 status = NT_STATUS_OK;
    1516             :         }
    1517           0 :         if (!NT_STATUS_IS_OK(status)) {
    1518           0 :                 return status;
    1519             :         }
    1520             : 
    1521           0 :         dom_sid_split_rid(mem_ctx, &group_sid, &dom_sid, &rid);
    1522             : 
    1523           0 :         map = talloc_zero(mem_ctx, GROUP_MAP);
    1524           0 :         if (map == NULL) {
    1525           0 :                 status = NT_STATUS_NO_MEMORY;
    1526           0 :                 goto done;
    1527             :         }
    1528             : 
    1529           0 :         map->nt_name = talloc_strdup(map, sAMAccountName);
    1530           0 :         if (map->nt_name == NULL) {
    1531           0 :                 status = NT_STATUS_NO_MEMORY;
    1532           0 :                 goto done;
    1533             :         }
    1534             : 
    1535           0 :         if (description) {
    1536           0 :                 map->comment = talloc_strdup(map, description);
    1537             :         } else {
    1538           0 :                 map->comment = talloc_strdup(map, "");
    1539             :         }
    1540           0 :         if (map->comment == NULL) {
    1541           0 :                 status = NT_STATUS_NO_MEMORY;
    1542           0 :                 goto done;
    1543             :         }
    1544             : 
    1545           0 :         DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
    1546             :                  map->nt_name,
    1547             :                  dom_sid_str_buf(&group_sid, &sid_str),
    1548             :                  num_members));
    1549             : 
    1550           0 :         status = dssync_insert_obj(pctx, pctx->aliases, obj);
    1551           0 :         if (!NT_STATUS_IS_OK(status)) {
    1552           0 :                 goto done;
    1553             :         }
    1554             : 
    1555           0 :         if (pdb_getgrsid(map, group_sid)) {
    1556           0 :                 if (map->gid != -1) {
    1557           0 :                         grp = getgrgid(map->gid);
    1558             :                 }
    1559           0 :                 insert = false;
    1560             :         }
    1561             : 
    1562           0 :         if (grp == NULL) {
    1563           0 :                 gid_t gid;
    1564             : 
    1565             :                 /* No group found from mapping, find it from its name. */
    1566           0 :                 if ((grp = getgrnam(map->nt_name)) == NULL) {
    1567             : 
    1568             :                         /* No appropriate group found, create one */
    1569             : 
    1570           0 :                         DEBUG(0, ("Creating unix group: '%s'\n",
    1571             :                                                         map->nt_name));
    1572             : 
    1573           0 :                         if (smb_create_group(map->nt_name, &gid) != 0) {
    1574           0 :                                 status = NT_STATUS_ACCESS_DENIED;
    1575           0 :                                 goto done;
    1576             :                         }
    1577             : 
    1578           0 :                         if ((grp = getgrgid(gid)) == NULL) {
    1579           0 :                                 status = NT_STATUS_ACCESS_DENIED;
    1580           0 :                                 goto done;
    1581             :                         }
    1582             :                 }
    1583             :         }
    1584             : 
    1585           0 :         map->gid = grp->gr_gid;
    1586           0 :         map->sid = group_sid;
    1587             : 
    1588           0 :         if (dom_sid_equal(dom_sid, &global_sid_Builtin)) {
    1589             :                 /*
    1590             :                  * pdb_ldap does not like SID_NAME_WKN_GRP...
    1591             :                  *
    1592             :                  * map.sid_name_use = SID_NAME_WKN_GRP;
    1593             :                  */
    1594           0 :                 map->sid_name_use = SID_NAME_ALIAS;
    1595             :         } else {
    1596           0 :                 map->sid_name_use = SID_NAME_ALIAS;
    1597             :         }
    1598             : 
    1599           0 :         if (insert) {
    1600           0 :                 pdb_add_group_mapping_entry(map);
    1601             :         } else {
    1602           0 :                 pdb_update_group_mapping_entry(map);
    1603             :         }
    1604             : 
    1605           0 :         for (i=0; i < num_members; i++) {
    1606           0 :                 struct dssync_passdb_mem *mem;
    1607             : 
    1608           0 :                 status = dssync_create_mem(pctx, obj,
    1609             :                                            true /* active */,
    1610           0 :                                            &members[i], &mem);
    1611           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1612           0 :                         goto done;
    1613             :                 }
    1614             :         }
    1615             : 
    1616           0 :         status = NT_STATUS_OK;
    1617             : 
    1618           0 : done:
    1619           0 :         TALLOC_FREE(map);
    1620           0 :         return status;
    1621             : }
    1622             : 
    1623             : /****************************************************************
    1624             : ****************************************************************/
    1625             : 
    1626           0 : static NTSTATUS handle_group_object(struct dssync_passdb *pctx,
    1627             :                                     TALLOC_CTX *mem_ctx,
    1628             :                                     struct dssync_passdb_obj *obj)
    1629             : {
    1630           0 :         struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
    1631           0 :         NTSTATUS status;
    1632           0 :         struct group *grp = NULL;
    1633           0 :         struct dom_sid group_sid;
    1634           0 :         struct dom_sid_buf sid_str;
    1635           0 :         GROUP_MAP *map;
    1636           0 :         bool insert = true;
    1637             : 
    1638           0 :         const char *sAMAccountName;
    1639           0 :         const char *description;
    1640           0 :         uint32_t i;
    1641           0 :         uint32_t num_members = 0;
    1642           0 :         struct drsuapi_DsReplicaObjectIdentifier3 *members = NULL;
    1643             : 
    1644           0 :         group_sid = cur->object.identifier->sid;
    1645           0 :         GET_STRING_EX(sAMAccountName, true);
    1646           0 :         GET_STRING(description);
    1647             : 
    1648           0 :         status = find_drsuapi_attr_dn(obj, cur, DRSUAPI_ATTID_member,
    1649             :                                       &num_members, &members);
    1650           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_PROPSET_NOT_FOUND)) {
    1651           0 :                 status = NT_STATUS_OK;
    1652             :         }
    1653           0 :         if (!NT_STATUS_IS_OK(status)) {
    1654           0 :                 return status;
    1655             :         }
    1656             : 
    1657           0 :         map = talloc_zero(NULL, GROUP_MAP);
    1658           0 :         if (!map) {
    1659           0 :                 return NT_STATUS_NO_MEMORY;
    1660             :         }
    1661             : 
    1662           0 :         map->nt_name = talloc_strdup(map, sAMAccountName);
    1663           0 :         if (!map->nt_name) {
    1664           0 :                 status = NT_STATUS_NO_MEMORY;
    1665           0 :                 goto done;
    1666             :         }
    1667           0 :         if (description) {
    1668           0 :                 map->comment = talloc_strdup(map, description);
    1669             :         } else {
    1670           0 :                 map->comment = talloc_strdup(map, "");
    1671             :         }
    1672           0 :         if (!map->comment) {
    1673           0 :                 status = NT_STATUS_NO_MEMORY;
    1674           0 :                 goto done;
    1675             :         }
    1676             : 
    1677           0 :         DEBUG(0,("Creating group[%s] - %s members [%u]\n",
    1678             :                  map->nt_name,
    1679             :                  dom_sid_str_buf(&group_sid, &sid_str),
    1680             :                  num_members));
    1681             : 
    1682           0 :         status = dssync_insert_obj(pctx, pctx->groups, obj);
    1683           0 :         if (!NT_STATUS_IS_OK(status)) {
    1684           0 :                 goto done;
    1685             :         }
    1686             : 
    1687           0 :         if (pdb_getgrsid(map, group_sid)) {
    1688           0 :                 if (map->gid != -1) {
    1689           0 :                         grp = getgrgid(map->gid);
    1690             :                 }
    1691           0 :                 insert = false;
    1692             :         }
    1693             : 
    1694           0 :         if (grp == NULL) {
    1695           0 :                 gid_t gid;
    1696             : 
    1697             :                 /* No group found from mapping, find it from its name. */
    1698           0 :                 if ((grp = getgrnam(map->nt_name)) == NULL) {
    1699             : 
    1700             :                         /* No appropriate group found, create one */
    1701             : 
    1702           0 :                         DEBUG(0, ("Creating unix group: '%s'\n",
    1703             :                                                         map->nt_name));
    1704             : 
    1705           0 :                         if (smb_create_group(map->nt_name, &gid) != 0) {
    1706           0 :                                 status = NT_STATUS_ACCESS_DENIED;
    1707           0 :                                 goto done;
    1708             :                         }
    1709             : 
    1710           0 :                         if ((grp = getgrnam(map->nt_name)) == NULL) {
    1711           0 :                                 status = NT_STATUS_ACCESS_DENIED;
    1712           0 :                                 goto done;
    1713             :                         }
    1714             :                 }
    1715             :         }
    1716             : 
    1717           0 :         map->gid = grp->gr_gid;
    1718           0 :         map->sid = group_sid;
    1719           0 :         map->sid_name_use = SID_NAME_DOM_GRP;
    1720             : 
    1721           0 :         if (insert) {
    1722           0 :                 pdb_add_group_mapping_entry(map);
    1723             :         } else {
    1724           0 :                 pdb_update_group_mapping_entry(map);
    1725             :         }
    1726             : 
    1727           0 :         for (i=0; i < num_members; i++) {
    1728           0 :                 struct dssync_passdb_mem *mem;
    1729             : 
    1730           0 :                 status = dssync_create_mem(pctx, obj,
    1731             :                                            true /* active */,
    1732           0 :                                            &members[i], &mem);
    1733           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1734           0 :                         goto done;
    1735             :                 }
    1736             :         }
    1737             : 
    1738           0 :         status = NT_STATUS_OK;
    1739             : 
    1740           0 : done:
    1741           0 :         TALLOC_FREE(map);
    1742           0 :         return status;
    1743             : }
    1744             : 
    1745             : /****************************************************************
    1746             : ****************************************************************/
    1747             : 
    1748           0 : static NTSTATUS handle_interdomain_trust_object(struct dssync_passdb *pctx,
    1749             :                                                 TALLOC_CTX *mem_ctx,
    1750             :                                                 struct dssync_passdb_obj *obj)
    1751             : {
    1752           0 :         struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
    1753           0 :         DEBUG(0,("trust: %s\n", cur->object.identifier->dn));
    1754           0 :         return NT_STATUS_NOT_IMPLEMENTED;
    1755             : }
    1756             : 
    1757             : /****************************************************************
    1758             : ****************************************************************/
    1759             : 
    1760             : struct dssync_object_table_t {
    1761             :         uint32_t type;
    1762             :         NTSTATUS (*fn) (struct dssync_passdb *pctx,
    1763             :                         TALLOC_CTX *mem_ctx,
    1764             :                         struct dssync_passdb_obj *obj);
    1765             : };
    1766             : 
    1767             : static const struct dssync_object_table_t dssync_object_table[] = {
    1768             :         { ATYPE_NORMAL_ACCOUNT,         handle_account_object },
    1769             :         { ATYPE_WORKSTATION_TRUST,      handle_account_object },
    1770             :         { ATYPE_SECURITY_LOCAL_GROUP,   handle_alias_object },
    1771             :         { ATYPE_SECURITY_GLOBAL_GROUP,  handle_group_object },
    1772             :         { ATYPE_INTERDOMAIN_TRUST,      handle_interdomain_trust_object },
    1773             : };
    1774             : 
    1775             : /****************************************************************
    1776             : ****************************************************************/
    1777             : 
    1778           0 : static NTSTATUS parse_object(struct dssync_passdb *pctx,
    1779             :                              TALLOC_CTX *mem_ctx,
    1780             :                              struct drsuapi_DsReplicaObjectListItemEx *cur)
    1781             : {
    1782           0 :         NTSTATUS status = NT_STATUS_OK;
    1783           0 :         DATA_BLOB *blob = NULL;
    1784           0 :         uint32_t i = 0;
    1785           0 :         size_t a = 0;
    1786             : 
    1787           0 :         char *name = NULL;
    1788           0 :         uint32_t sam_type = 0;
    1789             : 
    1790           0 :         DEBUG(3, ("parsing object '%s'\n", cur->object.identifier->dn));
    1791             : 
    1792           0 :         for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
    1793           0 :                 struct drsuapi_DsReplicaAttribute *attr =
    1794           0 :                         &cur->object.attribute_ctr.attributes[i];
    1795             : 
    1796           0 :                 if (attr->value_ctr.num_values != 1) {
    1797           0 :                         continue;
    1798             :                 }
    1799             : 
    1800           0 :                 if (!attr->value_ctr.values[0].blob) {
    1801           0 :                         continue;
    1802             :                 }
    1803             : 
    1804           0 :                 blob = attr->value_ctr.values[0].blob;
    1805             : 
    1806           0 :                 switch (attr->attid) {
    1807           0 :                         case DRSUAPI_ATTID_sAMAccountName:
    1808           0 :                                 pull_string_talloc(mem_ctx, NULL, 0, &name,
    1809           0 :                                                    blob->data, blob->length,
    1810             :                                                    STR_UNICODE);
    1811           0 :                                 break;
    1812           0 :                         case DRSUAPI_ATTID_sAMAccountType:
    1813           0 :                                 sam_type = IVAL(blob->data, 0);
    1814           0 :                                 break;
    1815           0 :                         default:
    1816           0 :                                 break;
    1817             :                 }
    1818             :         }
    1819             : 
    1820           0 :         for (a=0; a < ARRAY_SIZE(dssync_object_table); a++) {
    1821           0 :                 if (sam_type == dssync_object_table[a].type) {
    1822           0 :                         if (dssync_object_table[a].fn) {
    1823           0 :                                 struct dssync_passdb_obj *obj = NULL;
    1824           0 :                                 status = dssync_create_obj(pctx, pctx->all,
    1825             :                                                            sam_type, cur, &obj);
    1826           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    1827           0 :                                         break;
    1828             :                                 }
    1829           0 :                                 status = dssync_object_table[a].fn(pctx,
    1830             :                                                                    mem_ctx,
    1831             :                                                                    obj);
    1832           0 :                                 break;
    1833             :                         }
    1834             :                 }
    1835             :         }
    1836             : 
    1837           0 :         return status;
    1838             : }
    1839             : 
    1840           0 : static NTSTATUS parse_link(struct dssync_passdb *pctx,
    1841             :                            TALLOC_CTX *mem_ctx,
    1842             :                            struct drsuapi_DsReplicaLinkedAttribute *cur)
    1843             : {
    1844           0 :         struct drsuapi_DsReplicaObjectIdentifier3 *id3;
    1845           0 :         const DATA_BLOB *blob;
    1846           0 :         enum ndr_err_code ndr_err;
    1847           0 :         NTSTATUS status;
    1848           0 :         bool active = false;
    1849           0 :         struct dssync_passdb_mem *mem;
    1850           0 :         struct dssync_passdb_obj *obj;
    1851             : 
    1852           0 :         if (cur->attid != DRSUAPI_ATTID_member) {
    1853           0 :                 return NT_STATUS_OK;
    1854             :         }
    1855             : 
    1856           0 :         if (cur->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) {
    1857           0 :                 active = true;
    1858             :         }
    1859             : 
    1860           0 :         DEBUG(3, ("parsing link '%s' - %s\n",
    1861             :                   cur->identifier->dn, active?"adding":"deleting"));
    1862             : 
    1863           0 :         blob = cur->value.blob;
    1864             : 
    1865           0 :         if (blob == NULL) {
    1866           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1867             :         }
    1868             : 
    1869           0 :         obj = dssync_search_obj_by_guid(pctx, pctx->all, &cur->identifier->guid);
    1870           0 :         if (obj == NULL) {
    1871           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1872             :         }
    1873             : 
    1874           0 :         id3 = talloc_zero(obj, struct drsuapi_DsReplicaObjectIdentifier3);
    1875           0 :         if (id3 == NULL) {
    1876           0 :                 return NT_STATUS_NO_MEMORY;
    1877             :         }
    1878             : 
    1879             :         /* windows sometimes sends an extra two pad bytes here */
    1880           0 :         ndr_err = ndr_pull_struct_blob(blob, id3, id3,
    1881             :                         (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
    1882           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1883           0 :                 status = ndr_map_error2ntstatus(ndr_err);
    1884           0 :                 return status;
    1885             :         }
    1886             : 
    1887           0 :         status = dssync_create_mem(pctx, obj,
    1888             :                                    active,
    1889             :                                    id3, &mem);
    1890           0 :         if (!NT_STATUS_IS_OK(status)) {
    1891           0 :                 return status;
    1892             :         }
    1893             : 
    1894           0 :         return NT_STATUS_OK;
    1895             : }
    1896             : 
    1897             : /****************************************************************
    1898             : ****************************************************************/
    1899             : 
    1900           0 : static NTSTATUS passdb_process_objects(struct dssync_context *ctx,
    1901             :                                        TALLOC_CTX *mem_ctx,
    1902             :                                        struct drsuapi_DsReplicaObjectListItemEx *cur,
    1903             :                                        struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr)
    1904             : {
    1905           0 :         NTSTATUS status = NT_STATUS_OK;
    1906           0 :         struct dssync_passdb *pctx =
    1907           0 :                 talloc_get_type_abort(ctx->private_data,
    1908             :                 struct dssync_passdb);
    1909             : 
    1910           0 :         for (; cur; cur = cur->next_object) {
    1911           0 :                 status = parse_object(pctx, mem_ctx, cur);
    1912           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1913           0 :                         goto out;
    1914             :                 }
    1915             :         }
    1916             : 
    1917           0 :  out:
    1918           0 :         return status;
    1919             : }
    1920             : 
    1921             : /****************************************************************
    1922             : ****************************************************************/
    1923             : 
    1924           0 : static NTSTATUS passdb_process_links(struct dssync_context *ctx,
    1925             :                                      TALLOC_CTX *mem_ctx,
    1926             :                                      uint32_t count,
    1927             :                                      struct drsuapi_DsReplicaLinkedAttribute *links,
    1928             :                                      struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr)
    1929             : {
    1930           0 :         NTSTATUS status = NT_STATUS_OK;
    1931           0 :         struct dssync_passdb *pctx =
    1932           0 :                 talloc_get_type_abort(ctx->private_data,
    1933             :                 struct dssync_passdb);
    1934           0 :         uint32_t i;
    1935             : 
    1936           0 :         for (i = 0; i < count; i++) {
    1937           0 :                 status = parse_link(pctx, mem_ctx, &links[i]);
    1938           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1939           0 :                         goto out;
    1940             :                 }
    1941             :         }
    1942             : 
    1943           0 :  out:
    1944           0 :         return status;
    1945             : }
    1946             : 
    1947             : /****************************************************************
    1948             : ****************************************************************/
    1949             : 
    1950             : const struct dssync_ops libnet_dssync_passdb_ops = {
    1951             :         .startup                = passdb_startup,
    1952             :         .process_objects        = passdb_process_objects,
    1953             :         .process_links          = passdb_process_links,
    1954             :         .finish                 = passdb_finish,
    1955             : };

Generated by: LCOV version 1.14