Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/http/gensec/basic.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   HTTP library - Basic authentication mechanism gensec module
5
6
   Copyright (C) 2014 Samuel Cabrero <samuelcabrero@kernevil.me>
7
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#include "includes.h"
23
#include <tevent.h>
24
#include "lib/util/tevent_ntstatus.h"
25
#include "auth/auth.h"
26
#include "auth/gensec/gensec.h"
27
#include "auth/gensec/gensec_internal.h"
28
#include "auth/credentials/credentials.h"
29
#include "lib/util/base64.h"
30
31
_PUBLIC_ NTSTATUS gensec_http_basic_init(TALLOC_CTX *);
32
33
struct gensec_http_basic_state {
34
  enum {
35
    GENSEC_HTTP_BASIC_START,
36
    GENSEC_HTTP_BASIC_DONE,
37
    GENSEC_HTTP_BASIC_ERROR,
38
  } step;
39
};
40
41
static NTSTATUS gensec_http_basic_client_start(struct gensec_security *gensec)
42
0
{
43
0
  struct gensec_http_basic_state *state;
44
45
0
  state = talloc_zero(gensec, struct gensec_http_basic_state);
46
0
  if (state == NULL) {
47
0
    return NT_STATUS_NO_MEMORY;
48
0
  }
49
0
  gensec->private_data = state;
50
51
0
  state->step = GENSEC_HTTP_BASIC_START;
52
53
0
  return NT_STATUS_OK;
54
0
}
55
56
struct gensec_http_basic_update_state {
57
  NTSTATUS status;
58
  DATA_BLOB out;
59
};
60
61
static NTSTATUS gensec_http_basic_update_internal(struct gensec_security *gensec_ctx,
62
              TALLOC_CTX *mem_ctx,
63
              const DATA_BLOB in,
64
              DATA_BLOB *out);
65
66
static struct tevent_req *gensec_http_basic_update_send(TALLOC_CTX *mem_ctx,
67
                struct tevent_context *ev,
68
                struct gensec_security *gensec_security,
69
                const DATA_BLOB in)
70
0
{
71
0
  struct tevent_req *req = NULL;
72
0
  struct gensec_http_basic_update_state *state = NULL;
73
0
  NTSTATUS status;
74
75
0
  req = tevent_req_create(mem_ctx, &state,
76
0
        struct gensec_http_basic_update_state);
77
0
  if (req == NULL) {
78
0
    return NULL;
79
0
  }
80
81
0
  status = gensec_http_basic_update_internal(gensec_security,
82
0
               state, in,
83
0
               &state->out);
84
0
  state->status = status;
85
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
86
0
    tevent_req_done(req);
87
0
    return tevent_req_post(req, ev);
88
0
  }
89
0
  if (tevent_req_nterror(req, status)) {
90
0
    return tevent_req_post(req, ev);
91
0
  }
92
93
0
  tevent_req_done(req);
94
0
  return tevent_req_post(req, ev);
95
0
}
96
97
static NTSTATUS gensec_http_basic_update_internal(struct gensec_security *gensec_ctx,
98
              TALLOC_CTX *mem_ctx,
99
              const DATA_BLOB in,
100
              DATA_BLOB *out)
101
0
{
102
0
  struct gensec_http_basic_state *state;
103
0
  struct cli_credentials *creds;
104
0
  char *tmp, *b64;
105
106
0
  state = talloc_get_type_abort(gensec_ctx->private_data,
107
0
              struct gensec_http_basic_state);
108
0
  creds = gensec_get_credentials(gensec_ctx);
109
110
0
  switch (gensec_ctx->gensec_role) {
111
0
  case GENSEC_CLIENT:
112
0
    switch (state->step) {
113
0
    case GENSEC_HTTP_BASIC_START:
114
0
      tmp = talloc_asprintf(mem_ctx, "%s\\%s:%s",
115
0
          cli_credentials_get_domain(creds),
116
0
          cli_credentials_get_username(creds),
117
0
          cli_credentials_get_password(creds));
118
0
      if (tmp == NULL) {
119
0
        state->step = GENSEC_HTTP_BASIC_ERROR;
120
0
        return NT_STATUS_NO_MEMORY;
121
0
      }
122
0
      talloc_keep_secret(tmp);
123
0
      *out = data_blob_string_const(tmp);
124
125
0
      b64 = base64_encode_data_blob(mem_ctx, *out);
126
0
      if (b64 == NULL) {
127
0
        state->step = GENSEC_HTTP_BASIC_ERROR;
128
0
        return NT_STATUS_NO_MEMORY;
129
0
      }
130
0
      talloc_keep_secret(b64);
131
0
      TALLOC_FREE(tmp);
132
133
0
      tmp = talloc_asprintf(mem_ctx, "Basic %s", b64);
134
0
      if (tmp == NULL) {
135
0
        state->step = GENSEC_HTTP_BASIC_ERROR;
136
0
        return NT_STATUS_NO_MEMORY;
137
0
      }
138
0
      talloc_keep_secret(tmp);
139
0
      TALLOC_FREE(b64);
140
141
0
      *out = data_blob_string_const(tmp);
142
0
      state->step = GENSEC_HTTP_BASIC_DONE;
143
0
      return NT_STATUS_OK;
144
145
0
    case GENSEC_HTTP_BASIC_DONE:
146
0
    case GENSEC_HTTP_BASIC_ERROR:
147
0
    default:
148
0
      break;
149
0
    }
150
0
    state->step = GENSEC_HTTP_BASIC_ERROR;
151
0
    return NT_STATUS_INTERNAL_ERROR;
152
153
0
  case GENSEC_SERVER:
154
0
    state->step = GENSEC_HTTP_BASIC_ERROR;
155
0
    return NT_STATUS_NOT_IMPLEMENTED;
156
0
  }
157
158
0
  state->step = GENSEC_HTTP_BASIC_ERROR;
159
0
  return NT_STATUS_INTERNAL_ERROR;
160
0
}
161
162
static NTSTATUS gensec_http_basic_update_recv(struct tevent_req *req,
163
                TALLOC_CTX *out_mem_ctx,
164
                DATA_BLOB *out)
165
0
{
166
0
  struct gensec_http_basic_update_state *state =
167
0
    tevent_req_data(req,
168
0
    struct gensec_http_basic_update_state);
169
0
  NTSTATUS status;
170
171
0
  *out = data_blob_null;
172
173
0
  if (tevent_req_is_nterror(req, &status)) {
174
0
    tevent_req_received(req);
175
0
    return status;
176
0
  }
177
178
0
  *out = state->out;
179
0
  talloc_steal(out_mem_ctx, state->out.data);
180
0
  status = state->status;
181
0
  tevent_req_received(req);
182
0
  return status;
183
0
}
184
185
static const struct gensec_security_ops gensec_http_basic_security_ops = {
186
  .name           = "http_basic",
187
  .auth_type      = 0,
188
  .client_start   = gensec_http_basic_client_start,
189
  .update_send    = gensec_http_basic_update_send,
190
  .update_recv    = gensec_http_basic_update_recv,
191
  .enabled        = true,
192
  .priority       = GENSEC_EXTERNAL,
193
};
194
195
_PUBLIC_ NTSTATUS gensec_http_basic_init(TALLOC_CTX *ctx)
196
0
{
197
0
  NTSTATUS status;
198
199
0
  status = gensec_register(ctx, &gensec_http_basic_security_ops);
200
0
  if (!NT_STATUS_IS_OK(status)) {
201
0
    DEBUG(0, ("Failed to register '%s' gensec backend!\n",
202
0
        gensec_http_basic_security_ops.name));
203
0
    return status;
204
0
  }
205
206
0
  return status;
207
0
}