LCOV - code coverage report
Current view: top level - nsswitch/libwbclient - wbc_pam.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 576 767 75.1 %
Date: 2024-02-14 10:14:15 Functions: 34 37 91.9 %

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

Generated by: LCOV version 1.14