Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/lsarpc/util_lsarpc.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Authentication utility functions
4
   Copyright (C) Sumit Bose 2010
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "includes.h"
21
#include "../librpc/gen_ndr/ndr_drsblobs.h"
22
#include "../librpc/gen_ndr/ndr_lsa.h"
23
#include "libcli/lsarpc/util_lsarpc.h"
24
25
static NTSTATUS ai_array_2_trust_domain_info_buffer(TALLOC_CTX *mem_ctx,
26
        uint32_t count,
27
        struct AuthenticationInformationArray *ai,
28
        struct lsa_TrustDomainInfoBuffer **_b)
29
0
{
30
0
  NTSTATUS status;
31
0
  struct lsa_TrustDomainInfoBuffer *b;
32
0
  int i;
33
34
0
  b = talloc_array(mem_ctx, struct lsa_TrustDomainInfoBuffer, count);
35
0
  if (b == NULL) {
36
0
    return NT_STATUS_NO_MEMORY;
37
0
  }
38
39
0
  for(i = 0; i < count; i++) {
40
0
    size_t size = 0;
41
0
    b[i].last_update_time = ai->array[i].LastUpdateTime;
42
0
    b[i].AuthType = ai->array[i].AuthType;
43
0
    switch(ai->array[i].AuthType) {
44
0
      case TRUST_AUTH_TYPE_NONE:
45
0
        b[i].data.size = 0;
46
0
        b[i].data.data = NULL;
47
0
        break;
48
0
      case TRUST_AUTH_TYPE_NT4OWF:
49
0
        if (ai->array[i].AuthInfo.nt4owf.size != 16) {
50
0
          status = NT_STATUS_INVALID_PARAMETER;
51
0
          goto fail;
52
0
        }
53
0
        b[i].data.data = (uint8_t *)talloc_memdup(b,
54
0
            &ai->array[i].AuthInfo.nt4owf.password.hash,
55
0
            16);
56
0
        if (b[i].data.data == NULL) {
57
0
          status = NT_STATUS_NO_MEMORY;
58
0
          goto fail;
59
0
        }
60
0
        break;
61
0
      case TRUST_AUTH_TYPE_CLEAR:
62
0
        if (!convert_string_talloc(b,
63
0
                 CH_UTF16LE, CH_UNIX,
64
0
                 ai->array[i].AuthInfo.clear.password,
65
0
                 ai->array[i].AuthInfo.clear.size,
66
0
                 &b[i].data.data,
67
0
                 &size)) {
68
0
          status = NT_STATUS_INVALID_PARAMETER;
69
0
          goto fail;
70
0
        }
71
0
        b[i].data.size = size;
72
0
        break;
73
0
      case TRUST_AUTH_TYPE_VERSION:
74
0
        if (ai->array[i].AuthInfo.version.size != 4) {
75
0
          status = NT_STATUS_INVALID_PARAMETER;
76
0
          goto fail;
77
0
        }
78
0
        b[i].data.size = 4;
79
0
        b[i].data.data = (uint8_t *)talloc_memdup(b,
80
0
             &ai->array[i].AuthInfo.version.version, 4);
81
0
        if (b[i].data.data == NULL) {
82
0
          status = NT_STATUS_NO_MEMORY;
83
0
          goto fail;
84
0
        }
85
0
        break;
86
0
      default:
87
0
        status = NT_STATUS_INVALID_PARAMETER;
88
0
        goto fail;
89
0
    }
90
0
  }
91
92
0
  *_b = b;
93
94
0
  return NT_STATUS_OK;
95
96
0
fail:
97
0
  talloc_free(b);
98
0
  return status;
99
0
}
100
101
static NTSTATUS trustauth_inout_blob_2_auth_info(TALLOC_CTX *mem_ctx,
102
            DATA_BLOB *inout_blob,
103
            uint32_t *count,
104
            struct lsa_TrustDomainInfoBuffer **current,
105
            struct lsa_TrustDomainInfoBuffer **previous)
106
0
{
107
0
  NTSTATUS status;
108
0
  struct trustAuthInOutBlob iopw;
109
0
  enum ndr_err_code ndr_err;
110
0
  TALLOC_CTX *tmp_ctx;
111
112
0
  tmp_ctx = talloc_new(mem_ctx);
113
0
  if (tmp_ctx == NULL) {
114
0
    return NT_STATUS_NO_MEMORY;
115
0
  }
116
117
0
  ndr_err = ndr_pull_struct_blob(inout_blob, tmp_ctx, &iopw,
118
0
            (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
119
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
120
0
    status = NT_STATUS_INVALID_PARAMETER;
121
0
    goto done;
122
0
  }
123
124
0
  *count = iopw.count;
125
126
0
  status = ai_array_2_trust_domain_info_buffer(mem_ctx, iopw.count,
127
0
                  &iopw.current, current);
128
0
  if (!NT_STATUS_IS_OK(status)) {
129
0
    goto done;
130
0
  }
131
132
0
  if (iopw.previous.count > 0) {
133
0
    status = ai_array_2_trust_domain_info_buffer(mem_ctx, iopw.count,
134
0
                   &iopw.previous, previous);
135
0
    if (!NT_STATUS_IS_OK(status)) {
136
0
      goto done;
137
0
    }
138
0
  } else {
139
0
    *previous = NULL;
140
0
  }
141
142
0
  status = NT_STATUS_OK;
143
144
0
done:
145
0
  talloc_free(tmp_ctx);
146
0
  return status;
147
0
}
148
149
NTSTATUS auth_blob_2_auth_info(TALLOC_CTX *mem_ctx,
150
             DATA_BLOB incoming, DATA_BLOB outgoing,
151
             struct lsa_TrustDomainInfoAuthInfo *auth_info)
152
0
{
153
0
  NTSTATUS status;
154
155
0
  if (incoming.length != 0) {
156
0
    status = trustauth_inout_blob_2_auth_info(mem_ctx,
157
0
          &incoming,
158
0
          &auth_info->incoming_count,
159
0
          &auth_info->incoming_current_auth_info,
160
0
          &auth_info->incoming_previous_auth_info);
161
0
    if (!NT_STATUS_IS_OK(status)) {
162
0
      return status;
163
0
    }
164
0
  } else {
165
0
    auth_info->incoming_count = 0;
166
0
    auth_info->incoming_current_auth_info = NULL;
167
0
    auth_info->incoming_previous_auth_info = NULL;
168
0
  }
169
170
0
  if (outgoing.length != 0) {
171
0
    status = trustauth_inout_blob_2_auth_info(mem_ctx,
172
0
          &outgoing,
173
0
          &auth_info->outgoing_count,
174
0
          &auth_info->outgoing_current_auth_info,
175
0
          &auth_info->outgoing_previous_auth_info);
176
0
    if (!NT_STATUS_IS_OK(status)) {
177
0
      return status;
178
0
    }
179
0
  } else {
180
0
    auth_info->outgoing_count = 0;
181
0
    auth_info->outgoing_current_auth_info = NULL;
182
0
    auth_info->outgoing_previous_auth_info = NULL;
183
0
  }
184
185
0
  return NT_STATUS_OK;
186
0
}
187
188
static NTSTATUS trust_domain_info_buffer_2_ai_array(TALLOC_CTX *mem_ctx,
189
                uint32_t count,
190
                struct lsa_TrustDomainInfoBuffer *b,
191
                struct AuthenticationInformationArray *ai)
192
0
{
193
0
  NTSTATUS status;
194
0
  int i;
195
196
0
  ai->count = count;
197
0
  ai->array = talloc_zero_array(mem_ctx, struct AuthenticationInformation,
198
0
              count);
199
0
  if (ai->array == NULL) {
200
0
    return NT_STATUS_NO_MEMORY;
201
0
  }
202
203
0
  for(i = 0; i < count; i++) {
204
0
    size_t size = 0;
205
0
    ai->array[i].LastUpdateTime = b[i].last_update_time;
206
0
    ai->array[i].AuthType = b[i].AuthType;
207
0
    switch(ai->array[i].AuthType) {
208
0
      case TRUST_AUTH_TYPE_NONE:
209
0
        ai->array[i].AuthInfo.none.size = 0;
210
0
        break;
211
0
      case TRUST_AUTH_TYPE_NT4OWF:
212
0
        if (b[i].data.size != 16) {
213
0
          status = NT_STATUS_INVALID_PARAMETER;
214
0
          goto fail;
215
0
        }
216
0
        memcpy(&ai->array[i].AuthInfo.nt4owf.password.hash,
217
0
               b[i].data.data, 16);
218
0
        break;
219
0
      case TRUST_AUTH_TYPE_CLEAR:
220
0
        if (!convert_string_talloc(ai->array,
221
0
                 CH_UNIX, CH_UTF16,
222
0
                 b[i].data.data,
223
0
                 b[i].data.size,
224
0
                 &ai->array[i].AuthInfo.clear.password,
225
0
                 &size)) {
226
0
          status = NT_STATUS_INVALID_PARAMETER;
227
0
          goto fail;
228
0
        }
229
0
        ai->array[i].AuthInfo.clear.size = size;
230
0
        break;
231
0
      case TRUST_AUTH_TYPE_VERSION:
232
0
        if (b[i].data.size != 4) {
233
0
          status = NT_STATUS_INVALID_PARAMETER;
234
0
          goto fail;
235
0
        }
236
0
        ai->array[i].AuthInfo.version.size = 4;
237
0
        memcpy(&ai->array[i].AuthInfo.version.version,
238
0
               b[i].data.data, 4);
239
0
        break;
240
0
      default:
241
0
        status = NT_STATUS_INVALID_PARAMETER;
242
0
        goto fail;
243
0
    }
244
0
  }
245
246
0
  return NT_STATUS_OK;
247
248
0
fail:
249
0
  talloc_free(ai->array);
250
0
  return status;
251
0
}
252
253
NTSTATUS auth_info_2_trustauth_inout(TALLOC_CTX *mem_ctx,
254
             uint32_t count,
255
             struct lsa_TrustDomainInfoBuffer *current,
256
             struct lsa_TrustDomainInfoBuffer *previous,
257
             struct trustAuthInOutBlob **iopw_out)
258
0
{
259
0
  NTSTATUS status;
260
0
  struct trustAuthInOutBlob *iopw;
261
262
0
  iopw = talloc_zero(mem_ctx, struct trustAuthInOutBlob);
263
0
  if (iopw == NULL) {
264
0
    return NT_STATUS_NO_MEMORY;
265
0
  }
266
267
0
  iopw->count = count;
268
0
  status = trust_domain_info_buffer_2_ai_array(iopw, count, current,
269
0
                 &iopw->current);
270
0
  if (!NT_STATUS_IS_OK(status)) {
271
0
    goto done;
272
0
  }
273
274
0
  if (previous != NULL) {
275
0
    status = trust_domain_info_buffer_2_ai_array(iopw, count,
276
0
                   previous,
277
0
                   &iopw->previous);
278
0
    if (!NT_STATUS_IS_OK(status)) {
279
0
      goto done;
280
0
    }
281
0
  } else {
282
0
    iopw->previous.count = 0;
283
0
    iopw->previous.array = NULL;
284
0
  }
285
286
0
  *iopw_out = iopw;
287
288
0
  status = NT_STATUS_OK;
289
290
0
done:
291
0
  return status;
292
0
}
293
294
static NTSTATUS auth_info_2_trustauth_inout_blob(TALLOC_CTX *mem_ctx,
295
             uint32_t count,
296
             struct lsa_TrustDomainInfoBuffer *current,
297
             struct lsa_TrustDomainInfoBuffer *previous,
298
             DATA_BLOB *inout_blob)
299
0
{
300
0
  NTSTATUS status;
301
0
  struct trustAuthInOutBlob *iopw = NULL;
302
0
  enum ndr_err_code ndr_err;
303
304
0
  status = auth_info_2_trustauth_inout(mem_ctx, count, current, previous, &iopw);
305
306
0
  if (!NT_STATUS_IS_OK(status)) {
307
0
    goto done;
308
0
  }
309
310
0
  ndr_err = ndr_push_struct_blob(inout_blob, mem_ctx,
311
0
            iopw,
312
0
            (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
313
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
314
0
    return NT_STATUS_INVALID_PARAMETER;
315
0
  }
316
317
0
  status = NT_STATUS_OK;
318
319
0
done:
320
0
  talloc_free(iopw);
321
0
  return status;
322
0
}
323
324
NTSTATUS auth_info_2_auth_blob(TALLOC_CTX *mem_ctx,
325
             struct lsa_TrustDomainInfoAuthInfo *auth_info,
326
             DATA_BLOB *incoming, DATA_BLOB *outgoing)
327
0
{
328
0
  NTSTATUS status;
329
330
0
  if (auth_info->incoming_count == 0) {
331
0
    incoming->length = 0;
332
0
    incoming->data = NULL;
333
0
  } else {
334
0
    status = auth_info_2_trustauth_inout_blob(mem_ctx,
335
0
           auth_info->incoming_count,
336
0
           auth_info->incoming_current_auth_info,
337
0
           auth_info->incoming_previous_auth_info,
338
0
           incoming);
339
0
    if (!NT_STATUS_IS_OK(status)) {
340
0
      return status;
341
0
    }
342
0
  }
343
344
0
  if (auth_info->outgoing_count == 0) {
345
0
    outgoing->length = 0;
346
0
    outgoing->data = NULL;
347
0
  } else {
348
0
    status = auth_info_2_trustauth_inout_blob(mem_ctx,
349
0
           auth_info->outgoing_count,
350
0
           auth_info->outgoing_current_auth_info,
351
0
           auth_info->outgoing_previous_auth_info,
352
0
           outgoing);
353
0
    if (!NT_STATUS_IS_OK(status)) {
354
0
      return status;
355
0
    }
356
0
  }
357
358
0
  return NT_STATUS_OK;
359
0
}