LCOV - code coverage report
Current view: top level - nsswitch/libwbclient - wbc_pam.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 610 810 75.3 %
Date: 2024-04-21 15:09:00 Functions: 35 37 94.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind client API
       5             : 
       6             :    Copyright (C) Gerald (Jerry) Carter 2007
       7             :    Copyright (C) Guenther Deschner 2008
       8             :    Copyright (C) Volker Lendecke 2009
       9             : 
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Library General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : /* Required Headers */
      25             : 
      26             : #include "replace.h"
      27             : #include "libwbclient.h"
      28             : #include "../winbind_client.h"
      29             : 
      30             : /* Authenticate a username/password pair */
      31             : _PUBLIC_
      32         136 : wbcErr wbcCtxAuthenticateUser(struct wbcContext *ctx,
      33             :                               const char *username, const char *password)
      34             : {
      35         136 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
      36           0 :         struct wbcAuthUserParams params;
      37             : 
      38         136 :         ZERO_STRUCT(params);
      39             : 
      40         136 :         params.account_name             = username;
      41         136 :         params.level                    = WBC_AUTH_USER_LEVEL_PLAIN;
      42         136 :         params.password.plaintext       = password;
      43             : 
      44         136 :         wbc_status = wbcCtxAuthenticateUserEx(ctx, &params, NULL, NULL);
      45         136 :         BAIL_ON_WBC_ERROR(wbc_status);
      46             : 
      47          98 : done:
      48         136 :         return wbc_status;
      49             : }
      50             : 
      51             : _PUBLIC_
      52         136 : wbcErr wbcAuthenticateUser(const char *username, const char *password)
      53             : {
      54         136 :         return wbcCtxAuthenticateUser(NULL, username, password);
      55             : }
      56             : 
      57        9091 : static bool sid_attr_compose(struct wbcSidWithAttr *s,
      58             :                              const struct wbcDomainSid *d,
      59             :                              uint32_t rid, uint32_t attr)
      60             : {
      61        9091 :         if (d->num_auths >= WBC_MAXSUBAUTHS) {
      62           0 :                 return false;
      63             :         }
      64        9091 :         s->sid = *d;
      65        9091 :         s->sid.sub_auths[s->sid.num_auths++] = rid;
      66        9091 :         s->attributes = attr;
      67        9091 :         return true;
      68             : }
      69             : 
      70        1385 : static void wbcAuthUserInfoDestructor(void *ptr)
      71             : {
      72        1385 :         struct wbcAuthUserInfo *i = (struct wbcAuthUserInfo *)ptr;
      73        1385 :         free(i->account_name);
      74        1385 :         free(i->user_principal);
      75        1385 :         free(i->full_name);
      76        1385 :         free(i->domain_name);
      77        1385 :         free(i->dns_domain_name);
      78        1385 :         free(i->logon_server);
      79        1385 :         free(i->logon_script);
      80        1385 :         free(i->profile_path);
      81        1385 :         free(i->home_directory);
      82        1385 :         free(i->home_drive);
      83        1385 :         free(i->sids);
      84        1385 : }
      85             : 
      86        1451 : static wbcErr wbc_create_auth_info(const struct winbindd_response *resp,
      87             :                                    struct wbcAuthUserInfo **_i)
      88             : {
      89        1451 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
      90           0 :         struct wbcAuthUserInfo *i;
      91           0 :         struct wbcDomainSid domain_sid;
      92           0 :         char *p;
      93        1451 :         uint32_t sn = 0;
      94           0 :         uint32_t j;
      95             : 
      96        1451 :         i = (struct wbcAuthUserInfo *)wbcAllocateMemory(
      97             :                 1, sizeof(struct wbcAuthUserInfo),
      98             :                 wbcAuthUserInfoDestructor);
      99        1451 :         BAIL_ON_PTR_ERROR(i, wbc_status);
     100             : 
     101        1451 :         i->user_flags        = resp->data.auth.info3.user_flgs;
     102             : 
     103        1451 :         i->account_name      = strdup(resp->data.auth.info3.user_name);
     104        1451 :         BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
     105        1451 :         if (resp->data.auth.validation_level == 6) {
     106        1289 :                 i->user_principal = strdup(resp->data.auth.info6.principal_name);
     107        1289 :                 BAIL_ON_PTR_ERROR(i->user_principal, wbc_status);
     108             :         } else {
     109         162 :                 i->user_principal = NULL;
     110             :         }
     111        1451 :         i->full_name = strdup(resp->data.auth.info3.full_name);
     112        1451 :         BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
     113        1451 :         i->domain_name       = strdup(resp->data.auth.info3.logon_dom);
     114        1451 :         BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
     115        1451 :         if (resp->data.auth.validation_level == 6) {
     116        1289 :                 i->dns_domain_name = strdup(resp->data.auth.info6.dns_domainname);
     117        1289 :                 BAIL_ON_PTR_ERROR(i->dns_domain_name, wbc_status);
     118             :         } else {
     119         162 :                 i->dns_domain_name = NULL;
     120             :         }
     121             : 
     122        1451 :         i->acct_flags        = resp->data.auth.info3.acct_flags;
     123        1451 :         memcpy(i->user_session_key,
     124        1451 :                resp->data.auth.user_session_key,
     125             :                sizeof(i->user_session_key));
     126        1451 :         memcpy(i->lm_session_key,
     127        1451 :                resp->data.auth.first_8_lm_hash,
     128             :                sizeof(i->lm_session_key));
     129             : 
     130        1451 :         i->logon_count               = resp->data.auth.info3.logon_count;
     131        1451 :         i->bad_password_count        = resp->data.auth.info3.bad_pw_count;
     132             : 
     133        1451 :         i->logon_time                = resp->data.auth.info3.logon_time;
     134        1451 :         i->logoff_time               = resp->data.auth.info3.logoff_time;
     135        1451 :         i->kickoff_time              = resp->data.auth.info3.kickoff_time;
     136        1451 :         i->pass_last_set_time        = resp->data.auth.info3.pass_last_set_time;
     137        1451 :         i->pass_can_change_time      = resp->data.auth.info3.pass_can_change_time;
     138        1451 :         i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;
     139             : 
     140        1451 :         i->logon_server      = strdup(resp->data.auth.info3.logon_srv);
     141        1451 :         BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
     142        1451 :         i->logon_script      = strdup(resp->data.auth.info3.logon_script);
     143        1451 :         BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
     144        1451 :         i->profile_path      = strdup(resp->data.auth.info3.profile_path);
     145        1451 :         BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
     146        1451 :         i->home_directory= strdup(resp->data.auth.info3.home_dir);
     147        1451 :         BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
     148        1451 :         i->home_drive        = strdup(resp->data.auth.info3.dir_drive);
     149        1451 :         BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);
     150             : 
     151        1451 :         i->num_sids  = 2;
     152        1451 :         i->num_sids  += resp->data.auth.info3.num_groups;
     153        1451 :         i->num_sids  += resp->data.auth.info3.num_other_sids;
     154             : 
     155        1451 :         i->sids      = (struct wbcSidWithAttr *)calloc(
     156        1451 :                 sizeof(struct wbcSidWithAttr), i->num_sids);
     157        1451 :         BAIL_ON_PTR_ERROR(i->sids, wbc_status);
     158             : 
     159        1451 :         wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
     160             :                                     &domain_sid);
     161        1451 :         BAIL_ON_WBC_ERROR(wbc_status);
     162             : 
     163        1451 :         sn = 0;
     164        1451 :         if (!sid_attr_compose(&i->sids[sn], &domain_sid,
     165        1451 :                               resp->data.auth.info3.user_rid, 0)) {
     166           0 :                 wbc_status = WBC_ERR_INVALID_SID;
     167           0 :                 goto done;
     168             :         }
     169        1451 :         sn++;
     170        1451 :         if (!sid_attr_compose(&i->sids[sn], &domain_sid,
     171        1451 :                               resp->data.auth.info3.group_rid, 0)) {
     172           0 :                 wbc_status = WBC_ERR_INVALID_SID;
     173           0 :                 goto done;
     174             :         }
     175        1451 :         sn++;
     176             : 
     177        1451 :         p = (char *)resp->extra_data.data;
     178        1451 :         if (!p) {
     179           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
     180           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     181             :         }
     182             : 
     183        7640 :         for (j=0; j < resp->data.auth.info3.num_groups; j++) {
     184           0 :                 uint32_t rid;
     185           0 :                 uint32_t attrs;
     186           0 :                 int ret;
     187        6189 :                 char *s = p;
     188        6189 :                 char *e = strchr(p, '\n');
     189        6189 :                 if (!e) {
     190           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     191           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     192             :                 }
     193        6189 :                 e[0] = '\0';
     194        6189 :                 p = &e[1];
     195             : 
     196        6189 :                 ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
     197        6189 :                 if (ret != 2) {
     198           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     199           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     200             :                 }
     201             : 
     202        6189 :                 if (!sid_attr_compose(&i->sids[sn], &domain_sid,
     203             :                                       rid, attrs)) {
     204           0 :                         wbc_status = WBC_ERR_INVALID_SID;
     205           0 :                         goto done;
     206             :                 }
     207        6189 :                 sn++;
     208             :         }
     209             : 
     210        4108 :         for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
     211           0 :                 uint32_t attrs;
     212           0 :                 int ret;
     213        2657 :                 char *s = p;
     214           0 :                 char *a;
     215        2657 :                 char *e = strchr(p, '\n');
     216        2657 :                 if (!e) {
     217           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     218           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     219             :                 }
     220        2657 :                 e[0] = '\0';
     221        2657 :                 p = &e[1];
     222             : 
     223        2657 :                 e = strchr(s, ':');
     224        2657 :                 if (!e) {
     225           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     226           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     227             :                 }
     228        2657 :                 e[0] = '\0';
     229        2657 :                 a = &e[1];
     230             : 
     231        2657 :                 ret = sscanf(a, "0x%08X",
     232             :                              &attrs);
     233        2657 :                 if (ret != 1) {
     234           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     235           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     236             :                 }
     237             : 
     238        2657 :                 wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
     239        2657 :                 BAIL_ON_WBC_ERROR(wbc_status);
     240             : 
     241        2657 :                 i->sids[sn].attributes = attrs;
     242        2657 :                 sn++;
     243             :         }
     244             : 
     245        1451 :         i->num_sids = sn;
     246             : 
     247        1451 :         *_i = i;
     248        1451 :         i = NULL;
     249        1451 : done:
     250        1451 :         wbcFreeMemory(i);
     251        1451 :         return wbc_status;
     252             : }
     253             : 
     254        2303 : static void wbcAuthErrorInfoDestructor(void *ptr)
     255             : {
     256        2303 :         struct wbcAuthErrorInfo *e = (struct wbcAuthErrorInfo *)ptr;
     257        2303 :         free(e->nt_string);
     258        2303 :         free(e->display_string);
     259        2303 : }
     260             : 
     261        2311 : static wbcErr wbc_create_error_info(const struct winbindd_response *resp,
     262             :                                     struct wbcAuthErrorInfo **_e)
     263             : {
     264        2311 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
     265           0 :         struct wbcAuthErrorInfo *e;
     266             : 
     267        2311 :         e = (struct wbcAuthErrorInfo *)wbcAllocateMemory(
     268             :                 1, sizeof(struct wbcAuthErrorInfo),
     269             :                 wbcAuthErrorInfoDestructor);
     270        2311 :         BAIL_ON_PTR_ERROR(e, wbc_status);
     271             : 
     272        2311 :         e->nt_status = resp->data.auth.nt_status;
     273        2311 :         e->pam_error = resp->data.auth.pam_error;
     274        2311 :         e->authoritative = resp->data.auth.authoritative;
     275        2311 :         e->nt_string = strdup(resp->data.auth.nt_status_string);
     276        2311 :         BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);
     277             : 
     278        2311 :         e->display_string = strdup(resp->data.auth.error_string);
     279        2311 :         BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
     280             : 
     281        2311 :         *_e = e;
     282        2311 :         e = NULL;
     283             : 
     284        2311 : done:
     285        2311 :         wbcFreeMemory(e);
     286        2311 :         return wbc_status;
     287             : }
     288             : 
     289          50 : static wbcErr wbc_create_password_policy_info(const struct winbindd_response *resp,
     290             :                                               struct wbcUserPasswordPolicyInfo **_i)
     291             : {
     292          50 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
     293           0 :         struct wbcUserPasswordPolicyInfo *i;
     294             : 
     295          50 :         i = (struct wbcUserPasswordPolicyInfo *)wbcAllocateMemory(
     296             :                 1, sizeof(struct wbcUserPasswordPolicyInfo), NULL);
     297          50 :         BAIL_ON_PTR_ERROR(i, wbc_status);
     298             : 
     299          50 :         i->min_passwordage   = resp->data.auth.policy.min_passwordage;
     300          50 :         i->min_length_password       = resp->data.auth.policy.min_length_password;
     301          50 :         i->password_history  = resp->data.auth.policy.password_history;
     302          50 :         i->password_properties       = resp->data.auth.policy.password_properties;
     303          50 :         i->expire            = resp->data.auth.policy.expire;
     304             : 
     305          50 :         *_i = i;
     306          50 :         i = NULL;
     307             : 
     308          50 : done:
     309          50 :         wbcFreeMemory(i);
     310          50 :         return wbc_status;
     311             : }
     312             : 
     313         186 : static void wbcLogonUserInfoDestructor(void *ptr)
     314             : {
     315         186 :         struct wbcLogonUserInfo *i = (struct wbcLogonUserInfo *)ptr;
     316         186 :         wbcFreeMemory(i->info);
     317         186 :         wbcFreeMemory(i->blobs);
     318         186 : }
     319             : 
     320         240 : static wbcErr wbc_create_logon_info(struct winbindd_response *resp,
     321             :                                     struct wbcLogonUserInfo **_i)
     322             : {
     323         240 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
     324           0 :         struct wbcLogonUserInfo *i;
     325             : 
     326         240 :         i = (struct wbcLogonUserInfo *)wbcAllocateMemory(
     327             :                 1, sizeof(struct wbcLogonUserInfo),
     328             :                 wbcLogonUserInfoDestructor);
     329         240 :         BAIL_ON_PTR_ERROR(i, wbc_status);
     330             : 
     331         240 :         wbc_status = wbc_create_auth_info(resp, &i->info);
     332         240 :         BAIL_ON_WBC_ERROR(wbc_status);
     333             : 
     334         240 :         if (resp->data.auth.krb5ccname[0] != '\0') {
     335          36 :                 wbc_status = wbcAddNamedBlob(&i->num_blobs,
     336             :                                              &i->blobs,
     337             :                                              "krb5ccname",
     338             :                                              0,
     339          36 :                                              (uint8_t *)resp->data.auth.krb5ccname,
     340          36 :                                              strlen(resp->data.auth.krb5ccname)+1);
     341          36 :                 BAIL_ON_WBC_ERROR(wbc_status);
     342             :         }
     343             : 
     344         240 :         if (resp->data.auth.unix_username[0] != '\0') {
     345         166 :                 wbc_status = wbcAddNamedBlob(&i->num_blobs,
     346             :                                              &i->blobs,
     347             :                                              "unix_username",
     348             :                                              0,
     349         166 :                                              (uint8_t *)resp->data.auth.unix_username,
     350         166 :                                              strlen(resp->data.auth.unix_username)+1);
     351         166 :                 BAIL_ON_WBC_ERROR(wbc_status);
     352             :         }
     353             : 
     354         240 :         *_i = i;
     355         240 :         i = NULL;
     356         240 : done:
     357         240 :         wbcFreeMemory(i);
     358         240 :         return wbc_status;
     359             : }
     360             : 
     361             : 
     362             : /* Authenticate with more detailed information */
     363             : _PUBLIC_
     364        3558 : wbcErr wbcCtxAuthenticateUserEx(struct wbcContext *ctx,
     365             :                                 const struct wbcAuthUserParams *params,
     366             :                                 struct wbcAuthUserInfo **info,
     367             :                                 struct wbcAuthErrorInfo **error)
     368             : {
     369        3558 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     370        3558 :         int cmd = 0;
     371           0 :         struct winbindd_request request;
     372           0 :         struct winbindd_response response;
     373             : 
     374        3558 :         ZERO_STRUCT(request);
     375        3558 :         ZERO_STRUCT(response);
     376             : 
     377        3558 :         if (error) {
     378        3422 :                 *error = NULL;
     379             :         }
     380             : 
     381        3558 :         if (!params) {
     382           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     383           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     384             :         }
     385             : 
     386        3558 :         if (params->level != WBC_AUTH_USER_LEVEL_PAC && !params->account_name) {
     387           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     388           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     389             :         }
     390             : 
     391             :         /* Initialize request */
     392             : 
     393        3558 :         switch (params->level) {
     394         160 :         case WBC_AUTH_USER_LEVEL_PLAIN:
     395         160 :                 cmd = WINBINDD_PAM_AUTH;
     396         160 :                 request.flags = WBFLAG_PAM_INFO3_TEXT |
     397             :                                 WBFLAG_PAM_USER_SESSION_KEY |
     398             :                                 WBFLAG_PAM_LMKEY;
     399             : 
     400         160 :                 if (!params->password.plaintext) {
     401           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     402           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     403             :                 }
     404             : 
     405         160 :                 if (params->domain_name && params->domain_name[0]) {
     406             :                         /* We need to get the winbind separator :-( */
     407           0 :                         struct winbindd_response sep_response;
     408             : 
     409           0 :                         ZERO_STRUCT(sep_response);
     410             : 
     411           0 :                         wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO,
     412             :                                                         NULL, &sep_response);
     413           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     414             : 
     415           0 :                         snprintf(request.data.auth.user,
     416             :                                  sizeof(request.data.auth.user)-1,
     417             :                                  "%s%c%s",
     418           0 :                                  params->domain_name,
     419           0 :                                  sep_response.data.info.winbind_separator,
     420           0 :                                  params->account_name);
     421           0 :                         winbindd_free_response(&sep_response);
     422             :                 } else {
     423         160 :                         strncpy(request.data.auth.user,
     424         160 :                                 params->account_name,
     425             :                                 sizeof(request.data.auth.user)-1);
     426             :                 }
     427             : 
     428         160 :                 strncpy(request.data.auth.pass,
     429         160 :                         params->password.plaintext,
     430             :                         sizeof(request.data.auth.pass)-1);
     431         160 :                 break;
     432             : 
     433           0 :         case WBC_AUTH_USER_LEVEL_HASH:
     434           0 :                 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
     435           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     436           0 :                 break;
     437             : 
     438        2522 :         case WBC_AUTH_USER_LEVEL_RESPONSE:
     439        2522 :                 cmd = WINBINDD_PAM_AUTH_CRAP;
     440        2522 :                 request.flags = WBFLAG_PAM_INFO3_TEXT |
     441             :                                 WBFLAG_PAM_USER_SESSION_KEY |
     442             :                                 WBFLAG_PAM_LMKEY;
     443             : 
     444        2522 :                 if (params->password.response.lm_length &&
     445        2470 :                     !params->password.response.lm_data) {
     446           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     447           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     448             :                 }
     449        2522 :                 if (params->password.response.lm_length == 0 &&
     450          52 :                     params->password.response.lm_data) {
     451           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     452           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     453             :                 }
     454             : 
     455        2522 :                 if (params->password.response.nt_length &&
     456        2506 :                     !params->password.response.nt_data) {
     457           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     458           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     459             :                 }
     460        2522 :                 if (params->password.response.nt_length == 0&&
     461          16 :                     params->password.response.nt_data) {
     462           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     463           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     464             :                 }
     465             : 
     466        2522 :                 strncpy(request.data.auth_crap.user,
     467        2522 :                         params->account_name,
     468             :                         sizeof(request.data.auth_crap.user)-1);
     469        2522 :                 if (params->domain_name) {
     470        2522 :                         strncpy(request.data.auth_crap.domain,
     471        2522 :                                 params->domain_name,
     472             :                                 sizeof(request.data.auth_crap.domain)-1);
     473             :                 }
     474        2522 :                 if (params->workstation_name) {
     475        2398 :                         strncpy(request.data.auth_crap.workstation,
     476        2398 :                                 params->workstation_name,
     477             :                                 sizeof(request.data.auth_crap.workstation)-1);
     478             :                 }
     479             : 
     480        2522 :                 request.data.auth_crap.logon_parameters =
     481        2522 :                                 params->parameter_control;
     482             : 
     483        2522 :                 memcpy(request.data.auth_crap.chal,
     484        2522 :                        params->password.response.challenge,
     485             :                        sizeof(request.data.auth_crap.chal));
     486             : 
     487        2522 :                 request.data.auth_crap.lm_resp_len =
     488        2522 :                                 MIN(params->password.response.lm_length,
     489             :                                     sizeof(request.data.auth_crap.lm_resp));
     490        2522 :                 if (params->password.response.lm_data) {
     491        2470 :                         memcpy(request.data.auth_crap.lm_resp,
     492        2470 :                                params->password.response.lm_data,
     493        2470 :                                request.data.auth_crap.lm_resp_len);
     494             :                 }
     495        2522 :                 request.data.auth_crap.nt_resp_len = params->password.response.nt_length;
     496        2522 :                 if (params->password.response.nt_length > sizeof(request.data.auth_crap.nt_resp)) {
     497        2343 :                         request.flags |= WBFLAG_BIG_NTLMV2_BLOB;
     498        2343 :                         request.extra_len = params->password.response.nt_length;
     499        2343 :                         request.extra_data.data = (char *)malloc(
     500        2343 :                                 request.extra_len);
     501        2343 :                         if (request.extra_data.data == NULL) {
     502           0 :                                 wbc_status = WBC_ERR_NO_MEMORY;
     503           0 :                                 BAIL_ON_WBC_ERROR(wbc_status);
     504             :                         }
     505        2343 :                         memcpy(request.extra_data.data,
     506        2343 :                                params->password.response.nt_data,
     507        2343 :                                request.data.auth_crap.nt_resp_len);
     508         179 :                 } else if (params->password.response.nt_data) {
     509         163 :                         memcpy(request.data.auth_crap.nt_resp,
     510         163 :                                params->password.response.nt_data,
     511         163 :                                request.data.auth_crap.nt_resp_len);
     512             :                 }
     513        2522 :                 break;
     514             : 
     515         876 :         case WBC_AUTH_USER_LEVEL_PAC:
     516         876 :                 cmd = WINBINDD_PAM_AUTH_CRAP;
     517         876 :                 request.flags = WBFLAG_PAM_AUTH_PAC | WBFLAG_PAM_INFO3_TEXT;
     518         876 :                 request.extra_data.data = malloc(params->password.pac.length);
     519         876 :                 if (request.extra_data.data == NULL) {
     520           0 :                         wbc_status = WBC_ERR_NO_MEMORY;
     521           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     522             :                 }
     523         876 :                 memcpy(request.extra_data.data, params->password.pac.data,
     524         876 :                        params->password.pac.length);
     525         876 :                 request.extra_len = params->password.pac.length;
     526         876 :                 break;
     527             : 
     528           0 :         default:
     529           0 :                 break;
     530             :         }
     531             : 
     532        3558 :         if (cmd == 0) {
     533           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     534           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     535             :         }
     536             : 
     537        3558 :         if (params->flags) {
     538           0 :                 request.flags |= params->flags;
     539             :         }
     540             : 
     541        3558 :         if (cmd == WINBINDD_PAM_AUTH_CRAP) {
     542        3398 :                 wbc_status = wbcRequestResponsePriv(ctx, cmd,
     543             :                                                     &request, &response);
     544             :         } else {
     545         160 :                 wbc_status = wbcRequestResponse(ctx, cmd,
     546             :                                                 &request, &response);
     547             :         }
     548        3558 :         if (response.data.auth.nt_status != 0) {
     549        2249 :                 if (error) {
     550        2211 :                         wbc_status = wbc_create_error_info(&response,
     551             :                                                            error);
     552        2211 :                         BAIL_ON_WBC_ERROR(wbc_status);
     553             :                 }
     554             : 
     555        2249 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     556        2249 :                 BAIL_ON_WBC_ERROR(wbc_status);
     557             :         }
     558        1309 :         BAIL_ON_WBC_ERROR(wbc_status);
     559             : 
     560        1309 :         if (info) {
     561        1211 :                 wbc_status = wbc_create_auth_info(&response, info);
     562        1211 :                 BAIL_ON_WBC_ERROR(wbc_status);
     563             :         }
     564             : 
     565        1309 : done:
     566        3558 :         winbindd_free_response(&response);
     567             : 
     568        3558 :         free(request.extra_data.data);
     569             : 
     570        3558 :         return wbc_status;
     571             : }
     572             : 
     573             : _PUBLIC_
     574        3422 : wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
     575             :                              struct wbcAuthUserInfo **info,
     576             :                              struct wbcAuthErrorInfo **error)
     577             : {
     578        3422 :         return wbcCtxAuthenticateUserEx(NULL, params, info, error);
     579             : }
     580             : 
     581             : /* Trigger a verification of the trust credentials of a specific domain */
     582             : _PUBLIC_
     583          44 : wbcErr wbcCtxCheckTrustCredentials(struct wbcContext *ctx, const char *domain,
     584             :                                    struct wbcAuthErrorInfo **error)
     585             : {
     586           0 :         struct winbindd_request request;
     587           0 :         struct winbindd_response response;
     588          44 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     589             : 
     590          44 :         ZERO_STRUCT(request);
     591          44 :         ZERO_STRUCT(response);
     592             : 
     593          44 :         if (domain) {
     594          44 :                 strncpy(request.domain_name, domain,
     595             :                         sizeof(request.domain_name)-1);
     596             :         }
     597             : 
     598             :         /* Send request */
     599             : 
     600          44 :         wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_CHECK_MACHACC,
     601             :                                             &request, &response);
     602          44 :         if (response.data.auth.nt_status != 0) {
     603           0 :                 if (error) {
     604           0 :                         wbc_status = wbc_create_error_info(&response,
     605             :                                                            error);
     606           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     607             :                 }
     608             : 
     609           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     610           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     611             :         }
     612          44 :         BAIL_ON_WBC_ERROR(wbc_status);
     613             : 
     614          44 :  done:
     615          44 :         return wbc_status;
     616             : }
     617             : 
     618             : _PUBLIC_
     619          44 : wbcErr wbcCheckTrustCredentials(const char *domain,
     620             :                                 struct wbcAuthErrorInfo **error)
     621             : {
     622          44 :         return wbcCtxCheckTrustCredentials(NULL, domain, error);
     623             : }
     624             : 
     625             : /* Trigger a change of the trust credentials for a specific domain */
     626             : _PUBLIC_
     627          28 : wbcErr wbcCtxChangeTrustCredentialsAt(struct wbcContext *ctx,
     628             :                                       const char *domain,
     629             :                                       const char *dcname,
     630             :                                       struct wbcAuthErrorInfo **error)
     631             : {
     632           0 :         struct winbindd_request request;
     633           0 :         struct winbindd_response response;
     634          28 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     635             : 
     636          28 :         ZERO_STRUCT(request);
     637          28 :         ZERO_STRUCT(response);
     638             : 
     639          28 :         if (domain) {
     640          28 :                 strncpy(request.domain_name, domain,
     641             :                         sizeof(request.domain_name)-1);
     642             :         }
     643             : 
     644          28 :         if (dcname != NULL) {
     645           2 :                 strncpy(request.data.init_conn.dcname, dcname,
     646             :                         sizeof(request.data.init_conn.dcname)-1);
     647             :         }
     648             : 
     649             :         /* Send request */
     650             : 
     651          28 :         wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_CHANGE_MACHACC,
     652             :                                             &request, &response);
     653          28 :         if (response.data.auth.nt_status != 0) {
     654           0 :                 if (error) {
     655           0 :                         wbc_status = wbc_create_error_info(&response,
     656             :                                                            error);
     657           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     658             :                 }
     659             : 
     660           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     661           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     662             :         }
     663          28 :         BAIL_ON_WBC_ERROR(wbc_status);
     664             : 
     665          28 :  done:
     666          28 :         return wbc_status;
     667             : }
     668             : 
     669             : _PUBLIC_
     670           2 : wbcErr wbcChangeTrustCredentialsAt(const char *domain,
     671             :                                  const char *dcname,
     672             :                                  struct wbcAuthErrorInfo **error)
     673             : {
     674           2 :         return wbcCtxChangeTrustCredentialsAt(NULL, domain, dcname, error);
     675             : }
     676             : 
     677             : _PUBLIC_
     678          26 : wbcErr wbcCtxChangeTrustCredentials(struct wbcContext *ctx,
     679             :                                     const char *domain,
     680             :                                     struct wbcAuthErrorInfo **error)
     681             : {
     682          26 :         return wbcCtxChangeTrustCredentialsAt(ctx, domain, NULL, error);
     683             : }
     684             : 
     685             : _PUBLIC_
     686          26 : wbcErr wbcChangeTrustCredentials(const char *domain,
     687             :                                  struct wbcAuthErrorInfo **error)
     688             : {
     689          26 :         return wbcCtxChangeTrustCredentials(NULL, domain, error);
     690             : }
     691             : 
     692             : /*
     693             :  * Trigger a no-op NETLOGON call. Lightweight version of
     694             :  * wbcCheckTrustCredentials
     695             :  */
     696             : _PUBLIC_
     697           0 : wbcErr wbcCtxPingDc(struct wbcContext *ctx, const char *domain,
     698             :                     struct wbcAuthErrorInfo **error)
     699             : {
     700           0 :         return wbcCtxPingDc2(ctx, domain, error, NULL);
     701             : }
     702             : 
     703             : _PUBLIC_
     704          16 : wbcErr wbcPingDc(const char *domain, struct wbcAuthErrorInfo **error)
     705             : {
     706          16 :         return wbcPingDc2(domain, error, NULL);
     707             : }
     708             : 
     709             : /*
     710             :  * Trigger a no-op NETLOGON call. Lightweight version of
     711             :  * wbcCheckTrustCredentials, optionally return attempted DC
     712             :  */
     713             : _PUBLIC_
     714         150 : wbcErr wbcCtxPingDc2(struct wbcContext *ctx, const char *domain,
     715             :                      struct wbcAuthErrorInfo **error, char **dcname)
     716             : {
     717           2 :         struct winbindd_request request;
     718           2 :         struct winbindd_response response;
     719         150 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     720             : 
     721         150 :         ZERO_STRUCT(request);
     722         150 :         ZERO_STRUCT(response);
     723             : 
     724         150 :         if (domain) {
     725         136 :                 strncpy(request.domain_name, domain,
     726             :                         sizeof(request.domain_name)-1);
     727             :         }
     728             : 
     729             :         /* Send request */
     730             : 
     731         150 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PING_DC,
     732             :                                         &request,
     733             :                                         &response);
     734             : 
     735         150 :         if (dcname && response.extra_data.data) {
     736           2 :                 size_t len;
     737             : 
     738         120 :                 len = response.length - sizeof(struct winbindd_response);
     739         120 :                 *dcname = wbcAllocateMemory(1, len, NULL);
     740         120 :                 BAIL_ON_PTR_ERROR(*dcname, wbc_status);
     741             : 
     742         120 :                 strlcpy(*dcname, response.extra_data.data, len);
     743             :         }
     744             : 
     745         150 :         if (response.data.auth.nt_status != 0) {
     746           0 :                 if (error) {
     747           0 :                         wbc_status = wbc_create_error_info(&response,
     748             :                                                            error);
     749           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     750             :                 }
     751             : 
     752           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     753           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     754             :         }
     755         150 :         BAIL_ON_WBC_ERROR(wbc_status);
     756             : 
     757         132 :  done:
     758         150 :         winbindd_free_response(&response);
     759         150 :         return wbc_status;
     760             : }
     761             : 
     762             : _PUBLIC_
     763         150 : wbcErr wbcPingDc2(const char *domain, struct wbcAuthErrorInfo **error,
     764             :                   char **dcname)
     765             : {
     766         150 :         return wbcCtxPingDc2(NULL, domain, error, dcname);
     767             : }
     768             : 
     769             : /* Trigger an extended logoff notification to Winbind for a specific user */
     770             : _PUBLIC_
     771           2 : wbcErr wbcCtxLogoffUserEx(struct wbcContext *ctx,
     772             :                           const struct wbcLogoffUserParams *params,
     773             :                           struct wbcAuthErrorInfo **error)
     774             : {
     775           0 :         struct winbindd_request request;
     776           0 :         struct winbindd_response response;
     777           2 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     778           0 :         size_t i;
     779             : 
     780             :         /* validate input */
     781             : 
     782           2 :         if (!params || !params->username) {
     783           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     784           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     785             :         }
     786             : 
     787           2 :         if ((params->num_blobs > 0) && (params->blobs == NULL)) {
     788           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     789           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     790             :         }
     791           2 :         if ((params->num_blobs == 0) && (params->blobs != NULL)) {
     792           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     793           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     794             :         }
     795             : 
     796           2 :         ZERO_STRUCT(request);
     797           2 :         ZERO_STRUCT(response);
     798             : 
     799           2 :         strncpy(request.data.logoff.user, params->username,
     800             :                 sizeof(request.data.logoff.user)-1);
     801             : 
     802           8 :         for (i=0; i<params->num_blobs; i++) {
     803             : 
     804           6 :                 if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) {
     805           2 :                         if (params->blobs[i].blob.data) {
     806           2 :                                 strncpy(request.data.logoff.krb5ccname,
     807           2 :                                         (const char *)params->blobs[i].blob.data,
     808             :                                         sizeof(request.data.logoff.krb5ccname) - 1);
     809             :                         }
     810           2 :                         continue;
     811             :                 }
     812             : 
     813           4 :                 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
     814           2 :                         if (params->blobs[i].blob.data) {
     815           2 :                                 memcpy(&request.data.logoff.uid,
     816           2 :                                         params->blobs[i].blob.data,
     817           2 :                                         MIN(params->blobs[i].blob.length,
     818             :                                             sizeof(request.data.logoff.uid)));
     819             :                         }
     820           2 :                         continue;
     821             :                 }
     822             : 
     823           2 :                 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
     824           2 :                         if (params->blobs[i].blob.data) {
     825           2 :                                 memcpy(&request.flags,
     826           2 :                                         params->blobs[i].blob.data,
     827           2 :                                         MIN(params->blobs[i].blob.length,
     828             :                                             sizeof(request.flags)));
     829             :                         }
     830           2 :                         continue;
     831             :                 }
     832             :         }
     833             : 
     834             :         /* Send request */
     835             : 
     836           2 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_LOGOFF,
     837             :                                         &request,
     838             :                                         &response);
     839             : 
     840             :         /* Take the response above and return it to the caller */
     841           2 :         if (response.data.auth.nt_status != 0) {
     842           0 :                 if (error) {
     843           0 :                         wbc_status = wbc_create_error_info(&response,
     844             :                                                            error);
     845           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     846             :                 }
     847             : 
     848           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     849           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     850             :         }
     851           2 :         BAIL_ON_WBC_ERROR(wbc_status);
     852             : 
     853           2 :  done:
     854           2 :         return wbc_status;
     855             : }
     856             : 
     857             : _PUBLIC_
     858           0 : wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params,
     859             :                        struct wbcAuthErrorInfo **error)
     860             : {
     861           0 :         return wbcCtxLogoffUserEx(NULL, params, error);
     862             : }
     863             : 
     864             : /* Trigger a logoff notification to Winbind for a specific user */
     865             : _PUBLIC_
     866          20 : wbcErr wbcCtxLogoffUser(struct wbcContext *ctx,
     867             :                         const char *username, uid_t uid,
     868             :                         const char *ccfilename)
     869             : {
     870           0 :         struct winbindd_request request;
     871           0 :         struct winbindd_response response;
     872          20 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     873             : 
     874             :         /* validate input */
     875             : 
     876          20 :         if (!username) {
     877           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     878           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     879             :         }
     880             : 
     881          20 :         ZERO_STRUCT(request);
     882          20 :         ZERO_STRUCT(response);
     883             : 
     884          20 :         strncpy(request.data.logoff.user, username,
     885             :                 sizeof(request.data.logoff.user)-1);
     886          20 :         request.data.logoff.uid = uid;
     887             : 
     888          20 :         if (ccfilename) {
     889          20 :                 strncpy(request.data.logoff.krb5ccname, ccfilename,
     890             :                         sizeof(request.data.logoff.krb5ccname)-1);
     891             :         }
     892             : 
     893             :         /* Send request */
     894             : 
     895          20 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_LOGOFF,
     896             :                                         &request,
     897             :                                         &response);
     898             : 
     899             :         /* Take the response above and return it to the caller */
     900             : 
     901          20 :  done:
     902          20 :         return wbc_status;
     903             : }
     904             : 
     905             : _PUBLIC_
     906          20 : wbcErr wbcLogoffUser(const char *username,
     907             :                      uid_t uid,
     908             :                      const char *ccfilename)
     909             : {
     910          20 :         return wbcCtxLogoffUser(NULL, username, uid, ccfilename);
     911             : }
     912             : 
     913             : /* Change a password for a user with more detailed information upon failure */
     914             : _PUBLIC_
     915          20 : wbcErr wbcCtxChangeUserPasswordEx(struct wbcContext *ctx,
     916             :                         const struct wbcChangePasswordParams *params,
     917             :                         struct wbcAuthErrorInfo **error,
     918             :                         enum wbcPasswordChangeRejectReason *reject_reason,
     919             :                         struct wbcUserPasswordPolicyInfo **policy)
     920             : {
     921           0 :         struct winbindd_request request;
     922           0 :         struct winbindd_response response;
     923          20 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     924          20 :         int cmd = 0;
     925             : 
     926             :         /* validate input */
     927             : 
     928          20 :         if (!params->account_name) {
     929           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     930           0 :                 goto done;
     931             :         }
     932             : 
     933          20 :         if (error) {
     934          12 :                 *error = NULL;
     935             :         }
     936             : 
     937          20 :         if (policy) {
     938          12 :                 *policy = NULL;
     939             :         }
     940             : 
     941          20 :         if (reject_reason) {
     942          12 :                 *reject_reason = -1;
     943             :         }
     944             : 
     945          20 :         ZERO_STRUCT(request);
     946          20 :         ZERO_STRUCT(response);
     947             : 
     948          20 :         switch (params->level) {
     949          16 :         case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
     950          16 :                 cmd = WINBINDD_PAM_CHAUTHTOK;
     951             : 
     952          16 :                 if (!params->account_name) {
     953           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     954           0 :                         goto done;
     955             :                 }
     956             : 
     957          16 :                 strncpy(request.data.chauthtok.user, params->account_name,
     958             :                         sizeof(request.data.chauthtok.user) - 1);
     959             : 
     960          16 :                 if (params->old_password.plaintext) {
     961          16 :                         strncpy(request.data.chauthtok.oldpass,
     962          16 :                                 params->old_password.plaintext,
     963             :                                 sizeof(request.data.chauthtok.oldpass) - 1);
     964             :                 }
     965             : 
     966          16 :                 if (params->new_password.plaintext) {
     967          16 :                         strncpy(request.data.chauthtok.newpass,
     968          16 :                                 params->new_password.plaintext,
     969             :                                 sizeof(request.data.chauthtok.newpass) - 1);
     970             :                 }
     971          16 :                 break;
     972             : 
     973           4 :         case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
     974           4 :                 cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
     975             : 
     976           4 :                 if (!params->account_name || !params->domain_name) {
     977           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     978           0 :                         goto done;
     979             :                 }
     980             : 
     981           4 :                 if (params->old_password.response.old_lm_hash_enc_length &&
     982           0 :                     !params->old_password.response.old_lm_hash_enc_data) {
     983           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     984           0 :                         goto done;
     985             :                 }
     986             : 
     987           4 :                 if (params->old_password.response.old_lm_hash_enc_length == 0 &&
     988           4 :                     params->old_password.response.old_lm_hash_enc_data) {
     989           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     990           0 :                         goto done;
     991             :                 }
     992             : 
     993           4 :                 if (params->old_password.response.old_nt_hash_enc_length &&
     994           4 :                     !params->old_password.response.old_nt_hash_enc_data) {
     995           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     996           0 :                         goto done;
     997             :                 }
     998             : 
     999           4 :                 if (params->old_password.response.old_nt_hash_enc_length == 0 &&
    1000           0 :                     params->old_password.response.old_nt_hash_enc_data) {
    1001           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1002           0 :                         goto done;
    1003             :                 }
    1004             : 
    1005           4 :                 if (params->new_password.response.lm_length &&
    1006           0 :                     !params->new_password.response.lm_data) {
    1007           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1008           0 :                         goto done;
    1009             :                 }
    1010             : 
    1011           4 :                 if (params->new_password.response.lm_length == 0 &&
    1012           4 :                     params->new_password.response.lm_data) {
    1013           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1014           0 :                         goto done;
    1015             :                 }
    1016             : 
    1017           4 :                 if (params->new_password.response.nt_length &&
    1018           4 :                     !params->new_password.response.nt_data) {
    1019           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1020           0 :                         goto done;
    1021             :                 }
    1022             : 
    1023           4 :                 if (params->new_password.response.nt_length == 0 &&
    1024           0 :                     params->new_password.response.nt_data) {
    1025           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1026           0 :                         goto done;
    1027             :                 }
    1028             : 
    1029           4 :                 strncpy(request.data.chng_pswd_auth_crap.user,
    1030           4 :                         params->account_name,
    1031             :                         sizeof(request.data.chng_pswd_auth_crap.user) - 1);
    1032             : 
    1033           4 :                 strncpy(request.data.chng_pswd_auth_crap.domain,
    1034           4 :                         params->domain_name,
    1035             :                         sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
    1036             : 
    1037           4 :                 if (params->new_password.response.nt_data) {
    1038           4 :                         request.data.chng_pswd_auth_crap.new_nt_pswd_len =
    1039           4 :                                 params->new_password.response.nt_length;
    1040           4 :                         memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
    1041           4 :                                params->new_password.response.nt_data,
    1042           4 :                                request.data.chng_pswd_auth_crap.new_nt_pswd_len);
    1043             :                 }
    1044             : 
    1045           4 :                 if (params->new_password.response.lm_data) {
    1046           0 :                         request.data.chng_pswd_auth_crap.new_lm_pswd_len =
    1047           0 :                                 params->new_password.response.lm_length;
    1048           0 :                         memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
    1049           0 :                                params->new_password.response.lm_data,
    1050           0 :                                request.data.chng_pswd_auth_crap.new_lm_pswd_len);
    1051             :                 }
    1052             : 
    1053           4 :                 if (params->old_password.response.old_nt_hash_enc_data) {
    1054           4 :                         request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
    1055           4 :                                 params->old_password.response.old_nt_hash_enc_length;
    1056           4 :                         memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
    1057           4 :                                params->old_password.response.old_nt_hash_enc_data,
    1058           4 :                                request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
    1059             :                 }
    1060             : 
    1061           4 :                 if (params->old_password.response.old_lm_hash_enc_data) {
    1062           0 :                         request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
    1063           0 :                                 params->old_password.response.old_lm_hash_enc_length;
    1064           0 :                         memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
    1065           0 :                                params->old_password.response.old_lm_hash_enc_data,
    1066           0 :                                request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
    1067             :                 }
    1068             : 
    1069           4 :                 break;
    1070           0 :         default:
    1071           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1072           0 :                 goto done;
    1073           0 :                 break;
    1074             :         }
    1075             : 
    1076             :         /* Send request */
    1077             : 
    1078          20 :         wbc_status = wbcRequestResponse(ctx, cmd,
    1079             :                                         &request,
    1080             :                                         &response);
    1081          20 :         if (WBC_ERROR_IS_OK(wbc_status)) {
    1082          20 :                 goto done;
    1083             :         }
    1084             : 
    1085             :         /* Take the response above and return it to the caller */
    1086             : 
    1087           0 :         if (response.data.auth.nt_status != 0) {
    1088           0 :                 if (error) {
    1089           0 :                         wbc_status = wbc_create_error_info(&response,
    1090             :                                                            error);
    1091           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
    1092             :                 }
    1093             : 
    1094             :         }
    1095             : 
    1096           0 :         if (policy) {
    1097           0 :                 wbc_status = wbc_create_password_policy_info(&response,
    1098             :                                                              policy);
    1099           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1100             :         }
    1101             : 
    1102           0 :         if (reject_reason) {
    1103           0 :                 *reject_reason = response.data.auth.reject_reason;
    1104             :         }
    1105             : 
    1106           0 :         wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
    1107           0 :         BAIL_ON_WBC_ERROR(wbc_status);
    1108             : 
    1109           0 :  done:
    1110          20 :         return wbc_status;
    1111             : }
    1112             : 
    1113             : _PUBLIC_
    1114           4 : wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
    1115             :                               struct wbcAuthErrorInfo **error,
    1116             :                               enum wbcPasswordChangeRejectReason *reject_reason,
    1117             :                               struct wbcUserPasswordPolicyInfo **policy)
    1118             : {
    1119           4 :         return wbcCtxChangeUserPasswordEx(NULL, params, error,
    1120             :                                           reject_reason, policy);
    1121             : }
    1122             : 
    1123             : /* Change a password for a user */
    1124             : _PUBLIC_
    1125           4 : wbcErr wbcCtxChangeUserPassword(struct wbcContext *ctx,
    1126             :                                 const char *username,
    1127             :                                 const char *old_password,
    1128             :                                 const char *new_password)
    1129             : {
    1130           4 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
    1131           0 :         struct wbcChangePasswordParams params;
    1132             : 
    1133           4 :         ZERO_STRUCT(params);
    1134             : 
    1135           4 :         params.account_name             = username;
    1136           4 :         params.level                    = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
    1137           4 :         params.old_password.plaintext   = old_password;
    1138           4 :         params.new_password.plaintext   = new_password;
    1139             : 
    1140           4 :         wbc_status = wbcCtxChangeUserPasswordEx(ctx, &params,
    1141             :                                                 NULL,
    1142             :                                                 NULL,
    1143             :                                                 NULL);
    1144           4 :         BAIL_ON_WBC_ERROR(wbc_status);
    1145             : 
    1146           4 : done:
    1147           4 :         return wbc_status;
    1148             : }
    1149             : 
    1150             : _PUBLIC_
    1151           4 : wbcErr wbcChangeUserPassword(const char *username,
    1152             :                              const char *old_password,
    1153             :                              const char *new_password)
    1154             : {
    1155           4 :         return wbcCtxChangeUserPassword(NULL, username,
    1156             :                                         old_password, new_password);
    1157             : }
    1158             : 
    1159             : /* Logon a User */
    1160             : _PUBLIC_
    1161         344 : wbcErr wbcCtxLogonUser(struct wbcContext *ctx,
    1162             :                        const struct wbcLogonUserParams *params,
    1163             :                        struct wbcLogonUserInfo **info,
    1164             :                        struct wbcAuthErrorInfo **error,
    1165             :                        struct wbcUserPasswordPolicyInfo **policy)
    1166             : {
    1167         344 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
    1168           0 :         struct winbindd_request request;
    1169           0 :         struct winbindd_response response;
    1170           0 :         uint32_t i;
    1171             : 
    1172         344 :         ZERO_STRUCT(request);
    1173         344 :         ZERO_STRUCT(response);
    1174             : 
    1175         344 :         if (info) {
    1176         344 :                 *info = NULL;
    1177             :         }
    1178         344 :         if (error) {
    1179         344 :                 *error = NULL;
    1180             :         }
    1181         344 :         if (policy) {
    1182          70 :                 *policy = NULL;
    1183             :         }
    1184             : 
    1185         344 :         if (!params) {
    1186           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1187           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1188             :         }
    1189             : 
    1190         344 :         if (!params->username) {
    1191           4 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1192           4 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1193             :         }
    1194             : 
    1195         340 :         if ((params->num_blobs > 0) && (params->blobs == NULL)) {
    1196           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1197           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1198             :         }
    1199         340 :         if ((params->num_blobs == 0) && (params->blobs != NULL)) {
    1200           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1201           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1202             :         }
    1203             : 
    1204             :         /* Initialize request */
    1205             : 
    1206         340 :         request.flags = WBFLAG_PAM_INFO3_TEXT |
    1207             :                         WBFLAG_PAM_USER_SESSION_KEY |
    1208             :                         WBFLAG_PAM_LMKEY;
    1209             : 
    1210         340 :         if (!params->password) {
    1211           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1212           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1213             :         }
    1214             : 
    1215         340 :         strncpy(request.data.auth.user,
    1216         340 :                 params->username,
    1217             :                 sizeof(request.data.auth.user)-1);
    1218             : 
    1219         340 :         strncpy(request.data.auth.pass,
    1220         340 :                 params->password,
    1221             :                 sizeof(request.data.auth.pass)-1);
    1222             : 
    1223        1170 :         for (i=0; i<params->num_blobs; i++) {
    1224             : 
    1225         830 :                 if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) {
    1226         166 :                         if (params->blobs[i].blob.data) {
    1227         166 :                                 strncpy(request.data.auth.krb5_cc_type,
    1228         166 :                                         (const char *)params->blobs[i].blob.data,
    1229             :                                         sizeof(request.data.auth.krb5_cc_type) - 1);
    1230             :                         }
    1231         166 :                         continue;
    1232             :                 }
    1233             : 
    1234         664 :                 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
    1235         320 :                         if (params->blobs[i].blob.data) {
    1236         320 :                                 memcpy(&request.data.auth.uid,
    1237         320 :                                         params->blobs[i].blob.data,
    1238         320 :                                         MIN(sizeof(request.data.auth.uid),
    1239             :                                             params->blobs[i].blob.length));
    1240             :                         }
    1241         320 :                         continue;
    1242             :                 }
    1243             : 
    1244         344 :                 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
    1245         324 :                         if (params->blobs[i].blob.data) {
    1246           0 :                                 uint32_t flags;
    1247         324 :                                 memcpy(&flags,
    1248         324 :                                         params->blobs[i].blob.data,
    1249         324 :                                         MIN(sizeof(flags),
    1250             :                                             params->blobs[i].blob.length));
    1251         324 :                                 request.flags |= flags;
    1252             :                         }
    1253         324 :                         continue;
    1254             :                 }
    1255             : 
    1256          20 :                 if (strcasecmp(params->blobs[i].name, "membership_of") == 0) {
    1257           8 :                         if (params->blobs[i].blob.data &&
    1258           8 :                             params->blobs[i].blob.data[0] > 0) {
    1259           8 :                                 strncpy(request.data.auth.require_membership_of_sid,
    1260           8 :                                         (const char *)params->blobs[i].blob.data,
    1261             :                                         sizeof(request.data.auth.require_membership_of_sid) - 1);
    1262             :                         }
    1263           8 :                         continue;
    1264             :                 }
    1265             :         }
    1266             : 
    1267         340 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_AUTH,
    1268             :                                         &request,
    1269             :                                         &response);
    1270             : 
    1271         340 :         if (response.data.auth.nt_status != 0) {
    1272         100 :                 if (error) {
    1273         100 :                         wbc_status = wbc_create_error_info(&response,
    1274             :                                                            error);
    1275         100 :                         BAIL_ON_WBC_ERROR(wbc_status);
    1276             :                 }
    1277             : 
    1278         100 :                 wbc_status = WBC_ERR_AUTH_ERROR;
    1279         100 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1280             :         }
    1281         240 :         BAIL_ON_WBC_ERROR(wbc_status);
    1282             : 
    1283         240 :         if (info) {
    1284         240 :                 wbc_status = wbc_create_logon_info(&response,
    1285             :                                                    info);
    1286         240 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1287             :         }
    1288             : 
    1289         240 :         if (policy) {
    1290          50 :                 wbc_status = wbc_create_password_policy_info(&response,
    1291             :                                                              policy);
    1292          50 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1293             :         }
    1294             : 
    1295         240 : done:
    1296         344 :         winbindd_free_response(&response);
    1297             : 
    1298         344 :         return wbc_status;
    1299             : }
    1300             : 
    1301             : _PUBLIC_
    1302          94 : wbcErr wbcLogonUser(const struct wbcLogonUserParams *params,
    1303             :                     struct wbcLogonUserInfo **info,
    1304             :                     struct wbcAuthErrorInfo **error,
    1305             :                     struct wbcUserPasswordPolicyInfo **policy)
    1306             : {
    1307          94 :         return wbcCtxLogonUser(NULL, params, info, error, policy);
    1308             : }
    1309             : 
    1310          64 : static void wbcCredentialCacheInfoDestructor(void *ptr)
    1311             : {
    1312          64 :         struct wbcCredentialCacheInfo *i =
    1313             :                 (struct wbcCredentialCacheInfo *)ptr;
    1314          64 :         wbcFreeMemory(i->blobs);
    1315          64 : }
    1316             : 
    1317             : /* Authenticate a user with cached credentials */
    1318             : _PUBLIC_
    1319          64 : wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
    1320             :                              struct wbcCredentialCacheParams *params,
    1321             :                              struct wbcCredentialCacheInfo **info,
    1322             :                              struct wbcAuthErrorInfo **error)
    1323             : {
    1324          64 :         wbcErr status = WBC_ERR_UNKNOWN_FAILURE;
    1325          64 :         struct wbcCredentialCacheInfo *result = NULL;
    1326           0 :         struct winbindd_request request;
    1327           0 :         struct winbindd_response response;
    1328          64 :         struct wbcNamedBlob *initial_blob = NULL;
    1329          64 :         struct wbcNamedBlob *challenge_blob = NULL;
    1330           0 :         size_t i;
    1331             : 
    1332          64 :         ZERO_STRUCT(request);
    1333          64 :         ZERO_STRUCT(response);
    1334             : 
    1335          64 :         *info = NULL;
    1336             : 
    1337          64 :         if (error != NULL) {
    1338          64 :                 *error = NULL;
    1339             :         }
    1340          64 :         if ((params == NULL)
    1341          64 :             || (params->account_name == NULL)
    1342          64 :             || (params->level != WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP)) {
    1343           0 :                 status = WBC_ERR_INVALID_PARAM;
    1344           0 :                 goto fail;
    1345             :         }
    1346             : 
    1347         172 :         for (i=0; i<params->num_blobs; i++) {
    1348             :                 /*
    1349             :                  * Older callers may used to provide the NEGOTIATE request
    1350             :                  * as "initial_blob", but it was completely ignored by winbindd.
    1351             :                  *
    1352             :                  * So we keep ignoring it.
    1353             :                  *
    1354             :                  * A new callers that is capable to support "new_spnego",
    1355             :                  * will provide the NEGOTIATE request as "negotiate_blob"
    1356             :                  * instead.
    1357             :                  */
    1358         108 :                 if (strcasecmp(params->blobs[i].name, "negotiate_blob") == 0) {
    1359          54 :                         if (initial_blob != NULL) {
    1360           0 :                                 status = WBC_ERR_INVALID_PARAM;
    1361           0 :                                 goto fail;
    1362             :                         }
    1363          54 :                         initial_blob = &params->blobs[i];
    1364          54 :                         continue;
    1365             :                 }
    1366          54 :                 if (strcasecmp(params->blobs[i].name, "challenge_blob") == 0) {
    1367          54 :                         if (challenge_blob != NULL) {
    1368           0 :                                 status = WBC_ERR_INVALID_PARAM;
    1369           0 :                                 goto fail;
    1370             :                         }
    1371          54 :                         challenge_blob = &params->blobs[i];
    1372          54 :                         continue;
    1373             :                 }
    1374             :         }
    1375             : 
    1376          64 :         if (params->domain_name != NULL) {
    1377          64 :                 status = wbcRequestResponse(ctx, WINBINDD_INFO,
    1378             :                                             NULL, &response);
    1379          64 :                 if (!WBC_ERROR_IS_OK(status)) {
    1380           0 :                         goto fail;
    1381             :                 }
    1382          64 :                 snprintf(request.data.ccache_ntlm_auth.user,
    1383             :                          sizeof(request.data.ccache_ntlm_auth.user)-1,
    1384             :                          "%s%c%s", params->domain_name,
    1385          64 :                          response.data.info.winbind_separator,
    1386             :                          params->account_name);
    1387             :         } else {
    1388           0 :                 strncpy(request.data.ccache_ntlm_auth.user,
    1389             :                         params->account_name,
    1390             :                         sizeof(request.data.ccache_ntlm_auth.user)-1);
    1391             :         }
    1392          64 :         request.data.ccache_ntlm_auth.uid = getuid();
    1393             : 
    1394          64 :         request.data.ccache_ntlm_auth.initial_blob_len = 0;
    1395          64 :         request.data.ccache_ntlm_auth.challenge_blob_len = 0;
    1396          64 :         request.extra_len = 0;
    1397             : 
    1398          64 :         if (initial_blob != NULL) {
    1399          54 :                 request.data.ccache_ntlm_auth.initial_blob_len =
    1400          54 :                         initial_blob->blob.length;
    1401          54 :                 request.extra_len += initial_blob->blob.length;
    1402             :         }
    1403          64 :         if (challenge_blob != NULL) {
    1404          54 :                 request.data.ccache_ntlm_auth.challenge_blob_len =
    1405          54 :                         challenge_blob->blob.length;
    1406          54 :                 request.extra_len += challenge_blob->blob.length;
    1407             :         }
    1408             : 
    1409          64 :         if (request.extra_len != 0) {
    1410          54 :                 request.extra_data.data = (char *)malloc(request.extra_len);
    1411          54 :                 if (request.extra_data.data == NULL) {
    1412           0 :                         status = WBC_ERR_NO_MEMORY;
    1413           0 :                         goto fail;
    1414             :                 }
    1415             :         }
    1416          64 :         if (initial_blob != NULL) {
    1417          54 :                 memcpy(request.extra_data.data,
    1418          54 :                        initial_blob->blob.data, initial_blob->blob.length);
    1419             :         }
    1420          64 :         if (challenge_blob != NULL) {
    1421          54 :                 memcpy(request.extra_data.data
    1422          54 :                        + request.data.ccache_ntlm_auth.initial_blob_len,
    1423          54 :                        challenge_blob->blob.data,
    1424             :                        challenge_blob->blob.length);
    1425             :         }
    1426             : 
    1427          64 :         status = wbcRequestResponse(ctx, WINBINDD_CCACHE_NTLMAUTH,
    1428             :                                     &request, &response);
    1429          64 :         if (!WBC_ERROR_IS_OK(status)) {
    1430           0 :                 goto fail;
    1431             :         }
    1432             : 
    1433          64 :         result = (struct wbcCredentialCacheInfo *)wbcAllocateMemory(
    1434             :                 1, sizeof(struct wbcCredentialCacheInfo),
    1435             :                 wbcCredentialCacheInfoDestructor);
    1436          64 :         if (result == NULL) {
    1437           0 :                 status = WBC_ERR_NO_MEMORY;
    1438           0 :                 goto fail;
    1439             :         }
    1440          64 :         result->num_blobs = 0;
    1441          64 :         result->blobs = NULL;
    1442          64 :         status = wbcAddNamedBlob(&result->num_blobs, &result->blobs,
    1443             :                                  "auth_blob", 0,
    1444          64 :                                  (uint8_t *)response.extra_data.data,
    1445          64 :                                  response.data.ccache_ntlm_auth.auth_blob_len);
    1446          64 :         if (!WBC_ERROR_IS_OK(status)) {
    1447           0 :                 goto fail;
    1448             :         }
    1449          64 :         status = wbcAddNamedBlob(
    1450             :                 &result->num_blobs, &result->blobs, "session_key", 0,
    1451             :                 response.data.ccache_ntlm_auth.session_key,
    1452             :                 sizeof(response.data.ccache_ntlm_auth.session_key));
    1453          64 :         if (!WBC_ERROR_IS_OK(status)) {
    1454           0 :                 goto fail;
    1455             :         }
    1456          64 :         if (response.data.ccache_ntlm_auth.new_spnego) {
    1457          44 :                 status = wbcAddNamedBlob(
    1458             :                         &result->num_blobs, &result->blobs, "new_spnego", 0,
    1459             :                         &response.data.ccache_ntlm_auth.new_spnego,
    1460             :                         sizeof(response.data.ccache_ntlm_auth.new_spnego));
    1461          44 :                 if (!WBC_ERROR_IS_OK(status)) {
    1462           0 :                         goto fail;
    1463             :                 }
    1464             :         }
    1465             : 
    1466          64 :         *info = result;
    1467          64 :         result = NULL;
    1468          64 :         status = WBC_ERR_SUCCESS;
    1469          64 : fail:
    1470          64 :         free(request.extra_data.data);
    1471          64 :         winbindd_free_response(&response);
    1472          64 :         wbcFreeMemory(result);
    1473          64 :         return status;
    1474             : }
    1475             : 
    1476             : _PUBLIC_
    1477          64 : wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
    1478             :                           struct wbcCredentialCacheInfo **info,
    1479             :                           struct wbcAuthErrorInfo **error)
    1480             : {
    1481          64 :         return wbcCtxCredentialCache(NULL, params, info, error);
    1482             : }
    1483             : 
    1484             : /* Authenticate a user with cached credentials */
    1485             : _PUBLIC_
    1486          66 : wbcErr wbcCtxCredentialSave(struct wbcContext *ctx,
    1487             :                             const char *user, const char *password)
    1488             : {
    1489           0 :         struct winbindd_request request;
    1490           0 :         struct winbindd_response response;
    1491             : 
    1492          66 :         ZERO_STRUCT(request);
    1493          66 :         ZERO_STRUCT(response);
    1494             : 
    1495          66 :         strncpy(request.data.ccache_save.user, user,
    1496             :                 sizeof(request.data.ccache_save.user)-1);
    1497          66 :         strncpy(request.data.ccache_save.pass, password,
    1498             :                 sizeof(request.data.ccache_save.pass)-1);
    1499          66 :         request.data.ccache_save.uid = getuid();
    1500             : 
    1501          66 :         return wbcRequestResponse(ctx, WINBINDD_CCACHE_SAVE, &request, &response);
    1502             : }
    1503             : 
    1504             : _PUBLIC_
    1505          66 : wbcErr wbcCredentialSave(const char *user, const char *password)
    1506             : {
    1507          66 :         return wbcCtxCredentialSave(NULL, user, password);
    1508             : }

Generated by: LCOV version 1.14