Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/libads/ads_struct.c
Line
Count
Source
1
/* 
2
   Unix SMB/CIFS implementation.
3
   ads (active directory) utility library
4
   Copyright (C) Andrew Tridgell 2001
5
   Copyright (C) Andrew Bartlett 2001
6
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
*/
20
21
#include "includes.h"
22
#include "ads.h"
23
24
/* return a ldap dn path from a string, given separators and field name
25
   caller must free
26
*/
27
ADS_STATUS ads_build_path(const char *realm,
28
        const char *sep,
29
        const char *field,
30
        int reverse,
31
        char **_path)
32
0
{
33
0
  char *p, *r;
34
0
  int numbits = 0;
35
0
  char *ret;
36
0
  int len;
37
0
  char *saveptr;
38
39
0
  *_path = NULL;
40
41
0
  r = SMB_STRDUP(realm);
42
0
  if (r == NULL) {
43
0
    return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
44
0
  }
45
46
0
  for (p=r; *p; p++) {
47
0
    if (strchr(sep, *p)) {
48
0
      numbits++;
49
0
    }
50
0
  }
51
52
0
  len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
53
54
0
  ret = (char *)SMB_MALLOC(len);
55
0
  if (!ret) {
56
0
    free(r);
57
0
    return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
58
0
  }
59
60
0
  if (strlcpy(ret,field, len) >= len) {
61
    /* Truncate ! */
62
0
    free(r);
63
0
    free(ret);
64
0
    return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
65
0
  }
66
0
  p=strtok_r(r, sep, &saveptr);
67
0
  if (p) {
68
0
    if (strlcat(ret, p, len) >= len) {
69
0
      free(r);
70
0
      free(ret);
71
0
      return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
72
0
    }
73
74
0
    while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) {
75
0
      int retval;
76
0
      char *s = NULL;
77
0
      if (reverse)
78
0
        retval = asprintf(&s, "%s%s,%s", field, p, ret);
79
0
      else
80
0
        retval = asprintf(&s, "%s,%s%s", ret, field, p);
81
0
      free(ret);
82
0
      if (retval == -1) {
83
0
        free(r);
84
0
        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
85
0
      }
86
0
      ret = SMB_STRDUP(s);
87
0
      free(s);
88
0
    }
89
0
  }
90
91
0
  free(r);
92
93
0
  *_path = ret;
94
95
0
  return ADS_ERROR_NT(NT_STATUS_OK);
96
0
}
97
98
/* return a dn of the form "dc=AA,dc=BB,dc=CC" from a 
99
   realm of the form AA.BB.CC 
100
   caller must free
101
*/
102
ADS_STATUS ads_build_dn(const char *realm, TALLOC_CTX *mem_ctx, char **_dn)
103
0
{
104
0
  ADS_STATUS status;
105
0
  char *dn = NULL;
106
107
0
  status = ads_build_path(realm, ".", "dc=", 0, &dn);
108
0
  if (!ADS_ERR_OK(status)) {
109
0
    SAFE_FREE(dn);
110
0
    return status;
111
0
  }
112
113
0
  *_dn = talloc_strdup(mem_ctx, dn);
114
0
  SAFE_FREE(dn);
115
0
  if (*_dn == NULL) {
116
0
    return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
117
0
  }
118
119
0
  return ADS_ERROR_NT(NT_STATUS_OK);
120
0
}
121
122
/* return a DNS name in the for aa.bb.cc from the DN  
123
   "dc=AA,dc=BB,dc=CC".  caller must free
124
*/
125
char *ads_build_domain(const char *dn)
126
0
{
127
0
  char *dnsdomain = NULL;
128
129
  /* result should always be shorter than the DN */
130
131
0
  if ( (dnsdomain = SMB_STRDUP( dn )) == NULL ) {
132
0
    DEBUG(0,("ads_build_domain: malloc() failed!\n"));   
133
0
    return NULL;   
134
0
  }  
135
136
0
  if (!strlower_m( dnsdomain )) {
137
0
    SAFE_FREE(dnsdomain);
138
0
    return NULL;
139
0
  }
140
141
0
  all_string_sub( dnsdomain, "dc=", "", 0);
142
0
  all_string_sub( dnsdomain, ",", ".", 0 );
143
144
0
  return dnsdomain; 
145
0
}
146
147
static int ads_destructor(ADS_STRUCT *ads)
148
0
{
149
0
#ifdef HAVE_LDAP
150
0
  ads_disconnect(ads);
151
0
#endif
152
0
  return 0;
153
0
}
154
155
/*
156
  initialise a ADS_STRUCT, ready for some ads_ ops
157
*/
158
ADS_STRUCT *ads_init(TALLOC_CTX *mem_ctx,
159
         const char *realm,
160
         const char *workgroup,
161
         const char *ldap_server,
162
         enum ads_sasl_state_e sasl_state)
163
0
{
164
0
  ADS_STRUCT *ads = NULL;
165
0
  int wrap_flags;
166
167
0
  ads = talloc_zero(mem_ctx, ADS_STRUCT);
168
0
  if (ads == NULL) {
169
0
    return NULL;
170
0
  }
171
0
  talloc_set_destructor(ads, ads_destructor);
172
173
0
#ifdef HAVE_LDAP
174
0
  ads_zero_ldap(ads);
175
0
#endif
176
177
0
  ads->server.realm = talloc_strdup(ads, realm);
178
0
  if (realm != NULL && ads->server.realm == NULL) {
179
0
    DBG_WARNING("Out of memory\n");
180
0
    TALLOC_FREE(ads);
181
0
    return NULL;
182
0
  }
183
184
0
  ads->server.workgroup = talloc_strdup(ads, workgroup);
185
0
  if (workgroup != NULL && ads->server.workgroup == NULL) {
186
0
    DBG_WARNING("Out of memory\n");
187
0
    TALLOC_FREE(ads);
188
0
    return NULL;
189
0
  }
190
191
0
  ads->server.ldap_server = talloc_strdup(ads, ldap_server);
192
0
  if (ldap_server != NULL && ads->server.ldap_server == NULL) {
193
0
    DBG_WARNING("Out of memory\n");
194
0
    TALLOC_FREE(ads);
195
0
    return NULL;
196
0
  }
197
198
0
  wrap_flags = lp_client_ldap_sasl_wrapping();
199
200
0
  if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
201
0
    sasl_state = ADS_SASL_PLAIN;
202
0
  } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
203
0
    sasl_state = ADS_SASL_PLAIN;
204
0
  }
205
206
0
  switch (sasl_state) {
207
0
  case ADS_SASL_PLAIN:
208
0
    break;
209
0
  case ADS_SASL_SIGN:
210
0
    wrap_flags |= ADS_AUTH_SASL_SIGN;
211
0
    break;
212
0
  case ADS_SASL_SEAL:
213
0
    wrap_flags |= ADS_AUTH_SASL_SEAL;
214
0
    break;
215
0
  }
216
217
0
  ads->auth.flags = wrap_flags;
218
219
0
  ads->auth.reconnect_state = talloc_zero(ads,
220
0
            struct ads_reconnect_state);
221
0
  if (ads->auth.reconnect_state == NULL) {
222
0
    TALLOC_FREE(ads);
223
0
    return NULL;
224
0
  }
225
226
  /* Start with the configured page size when the connection is new,
227
   * we will drop it by half we get a timeout.   */
228
0
  ads->config.ldap_page_size     = lp_ldap_page_size();
229
230
0
  return ads;
231
0
}
232
233
/****************************************************************
234
****************************************************************/
235
236
bool ads_set_sasl_wrap_flags(ADS_STRUCT *ads, unsigned flags)
237
0
{
238
0
  unsigned reset_flags;
239
0
  unsigned other_flags;
240
241
0
  if (!ads) {
242
0
    return false;
243
0
  }
244
245
0
  reset_flags = ADS_AUTH_SASL_SIGN |
246
0
          ADS_AUTH_SASL_SEAL |
247
0
          ADS_AUTH_SASL_LDAPS |
248
0
          ADS_AUTH_SASL_STARTTLS;
249
250
0
  other_flags = ads->auth.flags & ~reset_flags;
251
252
0
  ads->auth.flags = flags | other_flags;
253
254
  return true;
255
0
}