LCOV - code coverage report
Current view: top level - source3/libnet - libnet_join_offline.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 130 233 55.8 %
Date: 2024-01-11 09:59:51 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  libnet Join offline support
       4             :  *  Copyright (C) Guenther Deschner 2021
       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 "librpc/gen_ndr/ndr_libnet_join.h"
      22             : #include "../librpc/gen_ndr/ndr_ODJ.h"
      23             : #include "libnet/libnet_join_offline.h"
      24             : #include "libcli/security/dom_sid.h"
      25             : #include "rpc_client/util_netlogon.h"
      26             : 
      27          18 : static WERROR libnet_odj_compose_ODJ_WIN7BLOB(TALLOC_CTX *mem_ctx,
      28             :                                               const struct libnet_JoinCtx *r,
      29             :                                               struct ODJ_WIN7BLOB *b)
      30             : {
      31           0 :         char *samaccount;
      32           0 :         uint32_t len;
      33          18 :         struct ODJ_POLICY_DNS_DOMAIN_INFO i = {
      34             :                 .Sid = NULL,
      35             :         };
      36             : 
      37          18 :         ZERO_STRUCTP(b);
      38             : 
      39          18 :         b->lpDomain = talloc_strdup(mem_ctx, r->out.dns_domain_name);
      40          18 :         if (b->lpDomain == NULL) {
      41           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      42             :         }
      43             : 
      44          18 :         samaccount = talloc_strdup(mem_ctx, r->out.account_name);
      45          18 :         if (samaccount == NULL) {
      46           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      47             :         }
      48          18 :         len = strlen(samaccount);
      49          18 :         if (samaccount[len-1] == '$') {
      50          18 :                 samaccount[len-1] = '\0';
      51             :         }
      52          18 :         b->lpMachineName = samaccount;
      53             : 
      54          18 :         b->lpMachinePassword = talloc_strdup(mem_ctx, r->in.machine_password);
      55          18 :         if (b->lpMachinePassword == NULL) {
      56           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      57             :         }
      58             : 
      59             :         /* fill up ODJ_POLICY_DNS_DOMAIN_INFO */
      60             : 
      61          18 :         i.Name.string = talloc_strdup(mem_ctx, r->out.netbios_domain_name);
      62          18 :         if (i.Name.string == NULL) {
      63           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      64             :         }
      65             : 
      66          18 :         i.DnsDomainName.string = talloc_strdup(mem_ctx, r->out.dns_domain_name);
      67          18 :         if (i.DnsDomainName.string == NULL) {
      68           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      69             :         }
      70             : 
      71          18 :         i.DnsForestName.string = talloc_strdup(mem_ctx, r->out.forest_name);
      72          18 :         if (i.DnsForestName.string == NULL) {
      73           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      74             :         }
      75             : 
      76          18 :         i.DomainGuid = r->out.domain_guid;
      77          18 :         i.Sid = dom_sid_dup(mem_ctx, r->out.domain_sid);
      78          18 :         if (i.Sid == NULL) {
      79           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      80             :         }
      81             : 
      82          18 :         b->DnsDomainInfo = i;
      83             : 
      84          18 :         if (r->out.dcinfo) {
      85           0 :                 struct netr_DsRGetDCNameInfo *p;
      86             : 
      87          18 :                 p = talloc_steal(mem_ctx, r->out.dcinfo);
      88          18 :                 if (p == NULL) {
      89           0 :                         return WERR_NOT_ENOUGH_MEMORY;
      90             :                 }
      91             : 
      92          18 :                 b->DcInfo = *p;
      93             :         }
      94             : 
      95             :         /*
      96             :          * According to
      97             :          * https://docs.microsoft.com/en-us/windows/win32/netmgmt/odj-odj_win7blob
      98             :          * it should be 0 but Windows 2019 always sets 6 - gd.
      99             :          */
     100          18 :         b->Options = 6;
     101             : 
     102          18 :         return WERR_OK;
     103             : }
     104             : 
     105           0 : static WERROR libnet_odj_compose_OP_JOINPROV2_PART(TALLOC_CTX *mem_ctx,
     106             :                                                    const struct libnet_JoinCtx *r,
     107             :                                                    struct OP_JOINPROV2_PART **p)
     108             : {
     109           0 :         struct OP_JOINPROV2_PART *b;
     110             : 
     111           0 :         b = talloc_zero(mem_ctx, struct OP_JOINPROV2_PART);
     112           0 :         if (b == NULL) {
     113           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     114             :         }
     115             : 
     116             :         /* TODO */
     117             : 
     118           0 :         *p = b;
     119             : 
     120           0 :         return WERR_INVALID_LEVEL;
     121             : }
     122             : 
     123          18 : static WERROR libnet_odj_compose_OP_JOINPROV3_PART(TALLOC_CTX *mem_ctx,
     124             :                                                    const struct libnet_JoinCtx *r,
     125             :                                                    struct OP_JOINPROV3_PART **p)
     126             : {
     127           0 :         struct OP_JOINPROV3_PART *b;
     128           0 :         struct dom_sid *sid;
     129             : 
     130          18 :         b = talloc_zero(mem_ctx, struct OP_JOINPROV3_PART);
     131          18 :         if (b == NULL) {
     132           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     133             :         }
     134             : 
     135          18 :         b->Rid = r->out.account_rid;
     136          18 :         sid = dom_sid_add_rid(mem_ctx, r->out.domain_sid, r->out.account_rid);
     137          18 :         if (sid == NULL) {
     138           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     139             :         }
     140             : 
     141          18 :         b->lpSid = dom_sid_string(mem_ctx, sid);
     142          18 :         if (b->lpSid == NULL) {
     143           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     144             :         }
     145             : 
     146          18 :         *p = b;
     147             : 
     148          18 :         return WERR_OK;
     149             : }
     150             : 
     151          36 : static WERROR libnet_odj_compose_OP_PACKAGE_PART(TALLOC_CTX *mem_ctx,
     152             :                                                  const struct libnet_JoinCtx *r,
     153             :                                                  const struct ODJ_WIN7BLOB *win7,
     154             :                                                  const char *join_provider_guid,
     155             :                                                  uint32_t flags,
     156             :                                                  struct OP_PACKAGE_PART *p)
     157             : {
     158           0 :         struct GUID guid;
     159           0 :         uint32_t level;
     160           0 :         WERROR werr;
     161             : 
     162          36 :         if (!NT_STATUS_IS_OK(GUID_from_string(join_provider_guid, &guid))) {
     163           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     164             :         }
     165             : 
     166          36 :         level = odj_switch_level_from_guid(&guid);
     167             : 
     168          36 :         p->PartType  = guid;
     169          36 :         p->ulFlags   = flags;
     170          36 :         p->part_len  = 0; /* autogenerated */
     171          36 :         p->Part = talloc_zero(mem_ctx, union OP_PACKAGE_PART_u);
     172          36 :         if (p->Part == NULL) {
     173           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     174             :         }
     175             : 
     176          36 :         switch (level) {
     177          18 :                 case 1: /* ODJ_GUID_JOIN_PROVIDER */
     178          18 :                         if (win7 == NULL) {
     179           0 :                                 return WERR_INVALID_PARAMETER;
     180             :                         }
     181          18 :                         p->Part->win7blob = *win7;
     182          18 :                         break;
     183           0 :                 case 2: /* ODJ_GUID_JOIN_PROVIDER2 */
     184           0 :                         werr = libnet_odj_compose_OP_JOINPROV2_PART(mem_ctx, r,
     185           0 :                                         &p->Part->join_prov2.p);
     186           0 :                         if (!W_ERROR_IS_OK(werr)) {
     187           0 :                                 return werr;
     188             :                         }
     189           0 :                         break;
     190          18 :                 case 3: /* ODJ_GUID_JOIN_PROVIDER3 */
     191          18 :                         werr = libnet_odj_compose_OP_JOINPROV3_PART(mem_ctx, r,
     192          18 :                                         &p->Part->join_prov3.p);
     193          18 :                         if (!W_ERROR_IS_OK(werr)) {
     194           0 :                                 return werr;
     195             :                         }
     196          18 :                         break;
     197           0 :                 default:
     198           0 :                         return WERR_INVALID_LEVEL;
     199             :         }
     200             : 
     201          36 :         return WERR_OK;
     202             : }
     203             : 
     204          18 : static WERROR libnet_odj_compose_OP_PACKAGE_PART_COLLECTION(TALLOC_CTX *mem_ctx,
     205             :                                                             const struct libnet_JoinCtx *r,
     206             :                                                             const struct ODJ_WIN7BLOB *win7,
     207             :                                                             struct OP_PACKAGE_PART_COLLECTION **pp)
     208             : {
     209           0 :         WERROR werr;
     210           0 :         struct OP_PACKAGE_PART_COLLECTION *p;
     211             : 
     212          18 :         p = talloc_zero(mem_ctx, struct OP_PACKAGE_PART_COLLECTION);
     213          18 :         if (p == NULL) {
     214           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     215             :         }
     216             : 
     217          18 :         p->cParts = 2;
     218          18 :         p->pParts = talloc_zero_array(p, struct OP_PACKAGE_PART, p->cParts);
     219          18 :         if (p->pParts == NULL) {
     220           0 :                 talloc_free(p);
     221           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     222             :         }
     223             : 
     224          18 :         werr = libnet_odj_compose_OP_PACKAGE_PART(p, r, win7,
     225             :                                                   ODJ_GUID_JOIN_PROVIDER,
     226             :                                                   OPSPI_PACKAGE_PART_ESSENTIAL,
     227             :                                                   &p->pParts[0]);
     228          18 :         if (!W_ERROR_IS_OK(werr)) {
     229           0 :                 talloc_free(p);
     230           0 :                 return werr;
     231             :         }
     232             : 
     233          18 :         werr = libnet_odj_compose_OP_PACKAGE_PART(p, r, NULL,
     234             :                                                   ODJ_GUID_JOIN_PROVIDER3,
     235             :                                                   0,
     236          18 :                                                   &p->pParts[1]);
     237          18 :         if (!W_ERROR_IS_OK(werr)) {
     238           0 :                 talloc_free(p);
     239           0 :                 return werr;
     240             :         }
     241             : 
     242          18 :         *pp = p;
     243             : 
     244          18 :         return WERR_OK;
     245             : }
     246             : 
     247          18 : static WERROR libnet_odj_compose_OP_PACKAGE(TALLOC_CTX *mem_ctx,
     248             :                                             const struct libnet_JoinCtx *r,
     249             :                                             const struct ODJ_WIN7BLOB *win7,
     250             :                                             struct OP_PACKAGE **pp)
     251             : {
     252           0 :         WERROR werr;
     253           0 :         struct OP_PACKAGE_PART_COLLECTION *c;
     254           0 :         struct OP_PACKAGE *p;
     255             : 
     256          18 :         p = talloc_zero(mem_ctx, struct OP_PACKAGE);
     257          18 :         if (p == NULL) {
     258           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     259             :         }
     260             : 
     261          18 :         werr = libnet_odj_compose_OP_PACKAGE_PART_COLLECTION(p, r, win7, &c);
     262          18 :         if (!W_ERROR_IS_OK(werr)) {
     263           0 :                 talloc_free(p);
     264           0 :                 return werr;
     265             :         }
     266             : 
     267          18 :         p->EncryptionType = GUID_zero();
     268             : 
     269          18 :         p->WrappedPartCollection.cbBlob = 0; /* autogenerated */
     270          18 :         p->WrappedPartCollection.w = talloc_zero(p,
     271             :                         struct OP_PACKAGE_PART_COLLECTION_serialized_ptr);
     272          18 :         if (p->WrappedPartCollection.w == NULL) {
     273           0 :                 talloc_free(p);
     274           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     275             :         }
     276             : 
     277          18 :         p->WrappedPartCollection.w->s.p = c;
     278             : 
     279          18 :         *pp = p;
     280             : 
     281          18 :         return WERR_OK;
     282             : }
     283             : 
     284          18 : WERROR libnet_odj_compose_ODJ_PROVISION_DATA(TALLOC_CTX *mem_ctx,
     285             :                                              const struct libnet_JoinCtx *r,
     286             :                                              struct ODJ_PROVISION_DATA **b_p)
     287             : {
     288           0 :         WERROR werr;
     289           0 :         struct ODJ_PROVISION_DATA *b;
     290           0 :         struct ODJ_WIN7BLOB win7;
     291           0 :         struct OP_PACKAGE *package;
     292             : 
     293          18 :         b = talloc_zero(mem_ctx, struct ODJ_PROVISION_DATA);
     294          18 :         if (b == NULL) {
     295           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     296             :         }
     297             : 
     298          18 :         b->ulVersion = 1;
     299          18 :         b->ulcBlobs  = 2;
     300          18 :         b->pBlobs    = talloc_zero_array(b, struct ODJ_BLOB, b->ulcBlobs);
     301          18 :         if (b->pBlobs == NULL) {
     302           0 :                 talloc_free(b);
     303           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     304             :         }
     305             : 
     306          18 :         werr = libnet_odj_compose_ODJ_WIN7BLOB(b, r, &win7);
     307          18 :         if (!W_ERROR_IS_OK(werr)) {
     308           0 :                 talloc_free(b);
     309           0 :                 return werr;
     310             :         }
     311             : 
     312          18 :         werr = libnet_odj_compose_OP_PACKAGE(b, r, &win7, &package);
     313          18 :         if (!W_ERROR_IS_OK(werr)) {
     314           0 :                 talloc_free(b);
     315           0 :                 return werr;
     316             :         }
     317             : 
     318          18 :         b->pBlobs[0].ulODJFormat = ODJ_WIN7_FORMAT;
     319          18 :         b->pBlobs[0].cbBlob = 0; /* autogenerated */
     320          18 :         b->pBlobs[0].pBlob = talloc_zero(b, union ODJ_BLOB_u);
     321          18 :         if (b->pBlobs[0].pBlob == NULL) {
     322           0 :                 talloc_free(b);
     323           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     324             :         }
     325          18 :         b->pBlobs[0].pBlob->odj_win7blob = win7;
     326             : 
     327          18 :         b->pBlobs[1].ulODJFormat = ODJ_WIN8_FORMAT;
     328          18 :         b->pBlobs[1].cbBlob = 0; /* autogenerated */
     329          18 :         b->pBlobs[1].pBlob = talloc_zero(b, union ODJ_BLOB_u);
     330          18 :         if (b->pBlobs[1].pBlob == NULL) {
     331           0 :                 talloc_free(b);
     332           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     333             :         }
     334          18 :         b->pBlobs[1].pBlob->op_package.p = package;
     335             : 
     336          18 :         *b_p = b;
     337             : 
     338          18 :         return WERR_OK;
     339             : }
     340             : 
     341          36 : WERROR libnet_odj_find_win7blob(const struct ODJ_PROVISION_DATA *r,
     342             :                                 struct ODJ_WIN7BLOB *win7blob)
     343             : {
     344           0 :         int i;
     345             : 
     346          36 :         if (r == NULL) {
     347           0 :                 return WERR_INVALID_PARAMETER;
     348             :         }
     349             : 
     350          36 :         for (i = 0; i < r->ulcBlobs; i++) {
     351             : 
     352          36 :                 struct ODJ_BLOB b = r->pBlobs[i];
     353             : 
     354          36 :                 switch (b.ulODJFormat) {
     355          36 :                 case ODJ_WIN7_FORMAT:
     356          36 :                         *win7blob = b.pBlob->odj_win7blob;
     357          36 :                         return WERR_OK;
     358             : 
     359           0 :                 case ODJ_WIN8_FORMAT: {
     360           0 :                         NTSTATUS status;
     361           0 :                         struct OP_PACKAGE_PART_COLLECTION *col;
     362           0 :                         struct GUID guid;
     363           0 :                         int k;
     364             : 
     365           0 :                         if (b.pBlob->op_package.p->WrappedPartCollection.w == NULL) {
     366           0 :                                 return WERR_BAD_FORMAT;
     367             :                         }
     368             : 
     369           0 :                         col = b.pBlob->op_package.p->WrappedPartCollection.w->s.p;
     370             : 
     371           0 :                         status = GUID_from_string(ODJ_GUID_JOIN_PROVIDER, &guid);
     372           0 :                         if (!NT_STATUS_IS_OK(status)) {
     373           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     374             :                         }
     375             : 
     376           0 :                         for (k = 0; k < col->cParts; k++) {
     377           0 :                                 if (GUID_equal(&guid, &col->pParts[k].PartType)) {
     378           0 :                                         *win7blob = col->pParts[k].Part->win7blob;
     379           0 :                                         return WERR_OK;
     380             :                                 }
     381             :                         }
     382           0 :                         break;
     383             :                 }
     384           0 :                 default:
     385           0 :                         return WERR_BAD_FORMAT;
     386             :                 }
     387             :         }
     388             : 
     389           0 :         return WERR_BAD_FORMAT;
     390             : }
     391             : 
     392             : 
     393          18 : WERROR libnet_odj_find_joinprov3(const struct ODJ_PROVISION_DATA *r,
     394             :                                  struct OP_JOINPROV3_PART *joinprov3)
     395             : {
     396           0 :         int i;
     397             : 
     398          18 :         if (r == NULL) {
     399           0 :                 return WERR_INVALID_PARAMETER;
     400             :         }
     401             : 
     402          36 :         for (i = 0; i < r->ulcBlobs; i++) {
     403             : 
     404          36 :                 struct ODJ_BLOB b = r->pBlobs[i];
     405             : 
     406          36 :                 switch (b.ulODJFormat) {
     407          18 :                 case ODJ_WIN7_FORMAT:
     408          18 :                         continue;
     409             : 
     410          18 :                 case ODJ_WIN8_FORMAT: {
     411           0 :                         NTSTATUS status;
     412           0 :                         struct OP_PACKAGE_PART_COLLECTION *col;
     413           0 :                         struct GUID guid;
     414           0 :                         int k;
     415             : 
     416          18 :                         if (b.pBlob->op_package.p->WrappedPartCollection.w == NULL) {
     417           0 :                                 return WERR_BAD_FORMAT;
     418             :                         }
     419             : 
     420          18 :                         col = b.pBlob->op_package.p->WrappedPartCollection.w->s.p;
     421             : 
     422          18 :                         status = GUID_from_string(ODJ_GUID_JOIN_PROVIDER3, &guid);
     423          18 :                         if (!NT_STATUS_IS_OK(status)) {
     424           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     425             :                         }
     426             : 
     427          36 :                         for (k = 0; k < col->cParts; k++) {
     428          36 :                                 if (GUID_equal(&guid, &col->pParts[k].PartType)) {
     429          18 :                                         *joinprov3 = *col->pParts[k].Part->join_prov3.p;
     430          18 :                                         return WERR_OK;
     431             :                                 }
     432             :                         }
     433           0 :                         break;
     434             :                 }
     435           0 :                 default:
     436           0 :                         return WERR_BAD_FORMAT;
     437             :                 }
     438             :         }
     439             : 
     440           0 :         return WERR_BAD_FORMAT;
     441             : }

Generated by: LCOV version 1.14