~zulcss/ubuntu/lucid/likewise-open/likewise-open-sru

« back to all changes in this revision

Viewing changes to samba/source/nsswitch/libwbclient/wbc_pam.c

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-08-27 08:56:20 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080827085620-5q0f58b9qtog9myq
Tags: 4.1.0.2956-0ubuntu1
* missing-likewise-logo.diff: removed
* fixed copyright notice
* updated Standards-Version to 3.8.0
* removed path from command in prerm
* removed stop in S runlevel

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
wbcErr wbcAuthenticateUser(const char *username,
35
35
                           const char *password)
36
36
{
 
37
        wbcErr wbc_status = WBC_ERR_SUCCESS;
 
38
        struct wbcAuthUserParams params;
 
39
 
 
40
        ZERO_STRUCT(params);
 
41
 
 
42
        params.account_name             = username;
 
43
        params.level                    = WBC_AUTH_USER_LEVEL_PLAIN;
 
44
        params.password.plaintext       = password;
 
45
 
 
46
        wbc_status = wbcAuthenticateUserEx(&params, NULL, NULL);
 
47
        BAIL_ON_WBC_ERROR(wbc_status);
 
48
 
 
49
done:
 
50
        return wbc_status;
 
51
}
 
52
 
 
53
static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
 
54
                                   const struct winbindd_response *resp,
 
55
                                   struct wbcAuthUserInfo **_i)
 
56
{
 
57
        wbcErr wbc_status = WBC_ERR_SUCCESS;
 
58
        struct wbcAuthUserInfo *i;
 
59
        struct wbcDomainSid domain_sid;
 
60
        char *p;
 
61
        uint32_t sn = 0;
 
62
        uint32_t j;
 
63
 
 
64
        i = talloc(mem_ctx, struct wbcAuthUserInfo);
 
65
        BAIL_ON_PTR_ERROR(i, wbc_status);
 
66
 
 
67
        i->user_flags   = resp->data.auth.info3.user_flgs;
 
68
 
 
69
        i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name);
 
70
        BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
 
71
        i->user_principal= NULL;
 
72
        i->full_name    = talloc_strdup(i, resp->data.auth.info3.full_name);
 
73
        BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
 
74
        i->domain_name  = talloc_strdup(i, resp->data.auth.info3.logon_dom);
 
75
        BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
 
76
        i->dns_domain_name= NULL;
 
77
 
 
78
        i->acct_flags   = resp->data.auth.info3.acct_flags;
 
79
        memcpy(i->user_session_key,
 
80
               resp->data.auth.user_session_key,
 
81
               sizeof(i->user_session_key));
 
82
        memcpy(i->lm_session_key,
 
83
               resp->data.auth.first_8_lm_hash,
 
84
               sizeof(i->lm_session_key));
 
85
 
 
86
        i->logon_count          = resp->data.auth.info3.logon_count;
 
87
        i->bad_password_count   = resp->data.auth.info3.bad_pw_count;
 
88
 
 
89
        i->logon_time           = resp->data.auth.info3.logon_time;
 
90
        i->logoff_time          = resp->data.auth.info3.logoff_time;
 
91
        i->kickoff_time         = resp->data.auth.info3.kickoff_time;
 
92
        i->pass_last_set_time   = resp->data.auth.info3.pass_last_set_time;
 
93
        i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time;
 
94
        i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;
 
95
 
 
96
        i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv);
 
97
        BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
 
98
        i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script);
 
99
        BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
 
100
        i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path);
 
101
        BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
 
102
        i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir);
 
103
        BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
 
104
        i->home_drive   = talloc_strdup(i, resp->data.auth.info3.dir_drive);
 
105
        BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);
 
106
 
 
107
        i->num_sids     = 2;
 
108
        i->num_sids     += resp->data.auth.info3.num_groups;
 
109
        i->num_sids     += resp->data.auth.info3.num_other_sids;
 
110
 
 
111
        i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
 
112
        BAIL_ON_PTR_ERROR(i->sids, wbc_status);
 
113
 
 
114
        wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
 
115
                                    &domain_sid);
 
116
        BAIL_ON_WBC_ERROR(wbc_status);
 
117
 
 
118
#define _SID_COMPOSE(s, d, r, a) { \
 
119
        (s).sid = d; \
 
120
        if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
 
121
                (s).sid.sub_auths[(s).sid.num_auths++] = r; \
 
122
        } else { \
 
123
                wbc_status = WBC_ERR_INVALID_SID; \
 
124
                BAIL_ON_WBC_ERROR(wbc_status); \
 
125
        } \
 
126
        (s).attributes = a; \
 
127
} while (0)
 
128
 
 
129
        sn = 0;
 
130
        _SID_COMPOSE(i->sids[sn], domain_sid,
 
131
                     resp->data.auth.info3.user_rid,
 
132
                     0);
 
133
        sn++;
 
134
        _SID_COMPOSE(i->sids[sn], domain_sid,
 
135
                     resp->data.auth.info3.group_rid,
 
136
                     0);
 
137
        sn++;
 
138
 
 
139
        p = (char *)resp->extra_data.data;
 
140
        if (!p) {
 
141
                wbc_status = WBC_ERR_INVALID_RESPONSE;
 
142
                BAIL_ON_WBC_ERROR(wbc_status);
 
143
        }
 
144
 
 
145
        for (j=0; j < resp->data.auth.info3.num_groups; j++) {
 
146
                uint32_t rid;
 
147
                uint32_t attrs;
 
148
                int ret;
 
149
                char *s = p;
 
150
                char *e = strchr(p, '\n');
 
151
                if (!e) {
 
152
                        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
153
                        BAIL_ON_WBC_ERROR(wbc_status);
 
154
                }
 
155
                e[0] = '\0';
 
156
                p = &e[1];
 
157
 
 
158
                ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
 
159
                if (ret != 2) {
 
160
                        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
161
                        BAIL_ON_WBC_ERROR(wbc_status);
 
162
                }
 
163
 
 
164
                _SID_COMPOSE(i->sids[sn], domain_sid,
 
165
                             rid, attrs);
 
166
                sn++;
 
167
        }
 
168
 
 
169
        for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
 
170
                uint32_t attrs;
 
171
                int ret;
 
172
                char *s = p;
 
173
                char *a;
 
174
                char *e = strchr(p, '\n');
 
175
                if (!e) {
 
176
                        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
177
                        BAIL_ON_WBC_ERROR(wbc_status);
 
178
                }
 
179
                e[0] = '\0';
 
180
                p = &e[1];
 
181
 
 
182
                e = strchr(s, ':');
 
183
                if (!e) {
 
184
                        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
185
                        BAIL_ON_WBC_ERROR(wbc_status);
 
186
                }
 
187
                e[0] = '\0';
 
188
                a = &e[1];
 
189
 
 
190
                ret = sscanf(a, "0x%08X",
 
191
                             &attrs);
 
192
                if (ret != 1) {
 
193
                        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
194
                        BAIL_ON_WBC_ERROR(wbc_status);
 
195
                }
 
196
 
 
197
                wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
 
198
                BAIL_ON_WBC_ERROR(wbc_status);
 
199
 
 
200
                i->sids[sn].attributes = attrs;
 
201
                sn++;
 
202
        }
 
203
 
 
204
        i->num_sids = sn;
 
205
 
 
206
        *_i = i;
 
207
        i = NULL;
 
208
done:
 
209
        talloc_free(i);
 
210
        return wbc_status;
 
211
}
 
212
 
 
213
static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx,
 
214
                                  const struct winbindd_response *resp,
 
215
                                  struct wbcAuthErrorInfo **_e)
 
216
{
 
217
        wbcErr wbc_status = WBC_ERR_SUCCESS;
 
218
        struct wbcAuthErrorInfo *e;
 
219
 
 
220
        e = talloc(mem_ctx, struct wbcAuthErrorInfo);
 
221
        BAIL_ON_PTR_ERROR(e, wbc_status);
 
222
 
 
223
        e->nt_status = resp->data.auth.nt_status;
 
224
        e->pam_error = resp->data.auth.pam_error;
 
225
        e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string);
 
226
        BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);
 
227
 
 
228
        e->display_string = talloc_strdup(e, resp->data.auth.error_string);
 
229
        BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
 
230
 
 
231
        *_e = e;
 
232
        e = NULL;
 
233
 
 
234
done:
 
235
        talloc_free(e);
 
236
        return wbc_status;
 
237
}
 
238
 
 
239
/** @brief Authenticate with more detailed information
 
240
 *
 
241
 * @param params       Input parameters, WBC_AUTH_USER_LEVEL_HASH
 
242
 *                     is not supported yet
 
243
 * @param info         Output details on WBC_ERR_SUCCESS
 
244
 * @param error        Output details on WBC_ERR_AUTH_ERROR
 
245
 *
 
246
 * @return #wbcErr
 
247
 **/
 
248
 
 
249
wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
 
250
                             struct wbcAuthUserInfo **info,
 
251
                             struct wbcAuthErrorInfo **error)
 
252
{
37
253
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 
254
        int cmd = 0;
38
255
        struct winbindd_request request;
39
256
        struct winbindd_response response;
40
257
 
41
 
        if (!username) {
 
258
        ZERO_STRUCT(request);
 
259
        ZERO_STRUCT(response);
 
260
 
 
261
        if (error) {
 
262
                *error = NULL;
 
263
        }
 
264
 
 
265
        if (!params) {
 
266
                wbc_status = WBC_ERR_INVALID_PARAM;
 
267
                BAIL_ON_WBC_ERROR(wbc_status);
 
268
        }
 
269
 
 
270
        if (!params->account_name) {
42
271
                wbc_status = WBC_ERR_INVALID_PARAM;
43
272
                BAIL_ON_WBC_ERROR(wbc_status);
44
273
        }
45
274
 
46
275
        /* Initialize request */
47
276
 
 
277
        switch (params->level) {
 
278
        case WBC_AUTH_USER_LEVEL_PLAIN:
 
279
                cmd = WINBINDD_PAM_AUTH;
 
280
                request.flags = WBFLAG_PAM_INFO3_TEXT |
 
281
                                WBFLAG_PAM_USER_SESSION_KEY |
 
282
                                WBFLAG_PAM_LMKEY;
 
283
 
 
284
                if (!params->password.plaintext) {
 
285
                        wbc_status = WBC_ERR_INVALID_PARAM;
 
286
                        BAIL_ON_WBC_ERROR(wbc_status);
 
287
                }
 
288
 
 
289
                if (params->domain_name && params->domain_name[0]) {
 
290
                        /* We need to get the winbind separator :-( */
 
291
                        struct winbindd_response sep_response;
 
292
 
 
293
                        ZERO_STRUCT(sep_response);
 
294
 
 
295
                        wbc_status = wbcRequestResponse(WINBINDD_INFO,
 
296
                                                        NULL, &sep_response);
 
297
                        BAIL_ON_WBC_ERROR(wbc_status);
 
298
 
 
299
                        snprintf(request.data.auth.user,
 
300
                                 sizeof(request.data.auth.user)-1,
 
301
                                 "%s%c%s",
 
302
                                 params->domain_name,
 
303
                                 sep_response.data.info.winbind_separator,
 
304
                                 params->account_name);
 
305
                } else {
 
306
                        strncpy(request.data.auth.user,
 
307
                                params->account_name,
 
308
                                sizeof(request.data.auth.user)-1);
 
309
                }
 
310
                strncpy(request.data.auth.pass,
 
311
                        params->password.plaintext,
 
312
                        sizeof(request.data.auth.user)-1);
 
313
                break;
 
314
 
 
315
        case WBC_AUTH_USER_LEVEL_HASH:
 
316
                wbc_status = WBC_ERR_NOT_IMPLEMENTED;
 
317
                BAIL_ON_WBC_ERROR(wbc_status);
 
318
                break;
 
319
 
 
320
        case WBC_AUTH_USER_LEVEL_RESPONSE:
 
321
                cmd = WINBINDD_PAM_AUTH_CRAP;
 
322
                request.flags = WBFLAG_PAM_INFO3_TEXT |
 
323
                                WBFLAG_PAM_USER_SESSION_KEY |
 
324
                                WBFLAG_PAM_LMKEY;
 
325
 
 
326
                if (params->password.response.lm_length &&
 
327
                    !params->password.response.lm_data) {
 
328
                        wbc_status = WBC_ERR_INVALID_PARAM;
 
329
                        BAIL_ON_WBC_ERROR(wbc_status);
 
330
                }
 
331
                if (params->password.response.lm_length == 0 &&
 
332
                    params->password.response.lm_data) {
 
333
                        wbc_status = WBC_ERR_INVALID_PARAM;
 
334
                        BAIL_ON_WBC_ERROR(wbc_status);
 
335
                }
 
336
 
 
337
                if (params->password.response.nt_length &&
 
338
                    !params->password.response.nt_data) {
 
339
                        wbc_status = WBC_ERR_INVALID_PARAM;
 
340
                        BAIL_ON_WBC_ERROR(wbc_status);
 
341
                }
 
342
                if (params->password.response.nt_length == 0&&
 
343
                    params->password.response.nt_data) {
 
344
                        wbc_status = WBC_ERR_INVALID_PARAM;
 
345
                        BAIL_ON_WBC_ERROR(wbc_status);
 
346
                }
 
347
 
 
348
                strncpy(request.data.auth_crap.user,
 
349
                        params->account_name,
 
350
                        sizeof(request.data.auth_crap.user)-1);
 
351
                if (params->domain_name) {
 
352
                        strncpy(request.data.auth_crap.domain,
 
353
                                params->domain_name,
 
354
                                sizeof(request.data.auth_crap.domain)-1);
 
355
                }
 
356
                if (params->workstation_name) {
 
357
                        strncpy(request.data.auth_crap.workstation,
 
358
                                params->workstation_name,
 
359
                                sizeof(request.data.auth_crap.workstation)-1);
 
360
                }
 
361
 
 
362
                request.data.auth_crap.logon_parameters =
 
363
                                params->parameter_control;
 
364
 
 
365
                memcpy(request.data.auth_crap.chal,
 
366
                       params->password.response.challenge,
 
367
                       sizeof(request.data.auth_crap.chal));
 
368
 
 
369
                request.data.auth_crap.lm_resp_len =
 
370
                                MIN(params->password.response.lm_length,
 
371
                                    sizeof(request.data.auth_crap.lm_resp));
 
372
                request.data.auth_crap.nt_resp_len =
 
373
                                MIN(params->password.response.nt_length,
 
374
                                    sizeof(request.data.auth_crap.nt_resp));
 
375
                if (params->password.response.lm_data) {
 
376
                        memcpy(request.data.auth_crap.lm_resp,
 
377
                               params->password.response.lm_data,
 
378
                               request.data.auth_crap.lm_resp_len);
 
379
                }
 
380
                if (params->password.response.nt_data) {
 
381
                        memcpy(request.data.auth_crap.nt_resp,
 
382
                               params->password.response.nt_data,
 
383
                               request.data.auth_crap.nt_resp_len);
 
384
                }
 
385
                break;
 
386
        default:
 
387
                break;
 
388
        }
 
389
 
 
390
        if (cmd == 0) {
 
391
                wbc_status = WBC_ERR_INVALID_PARAM;
 
392
                BAIL_ON_WBC_ERROR(wbc_status);
 
393
        }
 
394
 
 
395
        wbc_status = wbcRequestResponse(cmd,
 
396
                                        &request,
 
397
                                        &response);
 
398
        if (response.data.auth.nt_status != 0) {
 
399
                if (error) {
 
400
                        wbc_status = wbc_create_error_info(NULL,
 
401
                                                           &response,
 
402
                                                           error);
 
403
                        BAIL_ON_WBC_ERROR(wbc_status);
 
404
                }
 
405
 
 
406
                wbc_status = WBC_ERR_AUTH_ERROR;
 
407
                BAIL_ON_WBC_ERROR(wbc_status);
 
408
        }
 
409
        BAIL_ON_WBC_ERROR(wbc_status);
 
410
 
 
411
        if (info) {
 
412
                wbc_status = wbc_create_auth_info(NULL,
 
413
                                                  &response,
 
414
                                                  info);
 
415
                BAIL_ON_WBC_ERROR(wbc_status);
 
416
        }
 
417
 
 
418
done:
 
419
        if (response.extra_data.data)
 
420
                free(response.extra_data.data);
 
421
 
 
422
        return wbc_status;
 
423
}
 
424
 
 
425
/** @brief Trigger a verification of the trust credentials of a specific domain
 
426
 *
 
427
 * @param *domain      The name of the domain, only NULL for the default domain is
 
428
 *                     supported yet. Other values than NULL will result in
 
429
 *                     WBC_ERR_NOT_IMPLEMENTED.
 
430
 * @param error        Output details on WBC_ERR_AUTH_ERROR
 
431
 *
 
432
 * @return #wbcErr
 
433
 *
 
434
 **/
 
435
wbcErr wbcCheckTrustCredentials(const char *domain,
 
436
                                struct wbcAuthErrorInfo **error)
 
437
{
 
438
        struct winbindd_request request;
 
439
        struct winbindd_response response;
 
440
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 
441
 
 
442
        if (domain) {
 
443
                /*
 
444
                 * the current protocol doesn't support
 
445
                 * specifying a domain
 
446
                 */
 
447
                wbc_status = WBC_ERR_NOT_IMPLEMENTED;
 
448
                BAIL_ON_WBC_ERROR(wbc_status);
 
449
        }
 
450
 
48
451
        ZERO_STRUCT(request);
49
452
        ZERO_STRUCT(response);
50
453
 
51
 
        /* dst is already null terminated from the memset above */
52
 
 
53
 
        strncpy(request.data.auth.user, username,
54
 
                sizeof(request.data.auth.user)-1);
55
 
        strncpy(request.data.auth.pass, password,
56
 
                sizeof(request.data.auth.user)-1);
57
 
 
58
 
        wbc_status = wbcRequestResponse(WINBINDD_PAM_AUTH,
 
454
        /* Send request */
 
455
 
 
456
        wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
59
457
                                        &request,
60
458
                                        &response);
 
459
        if (response.data.auth.nt_status != 0) {
 
460
                if (error) {
 
461
                        wbc_status = wbc_create_error_info(NULL,
 
462
                                                           &response,
 
463
                                                           error);
 
464
                        BAIL_ON_WBC_ERROR(wbc_status);
 
465
                }
 
466
 
 
467
                wbc_status = WBC_ERR_AUTH_ERROR;
 
468
                BAIL_ON_WBC_ERROR(wbc_status);
 
469
        }
61
470
        BAIL_ON_WBC_ERROR(wbc_status);
62
471
 
63
 
done:
 
472
 done:
64
473
        return wbc_status;
65
474
}