LCOV - code coverage report
Current view: top level - source3/libnet - libnet_join_offline.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 129 202 63.9 %
Date: 2021-09-23 10:06:22 Functions: 8 10 80.0 %

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

Generated by: LCOV version 1.13