LCOV - code coverage report
Current view: top level - nsswitch/libwbclient - wbc_pam.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 571 761 75.0 %
Date: 2024-06-13 04:01:37 Functions: 32 35 91.4 %

          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         110 :         BAIL_ON_WBC_ERROR(wbc_status);
      46             : 
      47         125 : 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         527 :                               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         527 :                               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       10254 :         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        2518 :         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          38 :                 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         243 :                 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          49 :                                 params->account_name,
     424             :                                 sizeof(request.data.auth.user)-1);
     425             :                 }
     426             : 
     427         108 :                 strncpy(request.data.auth.pass,
     428          49 :                         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         440 :                 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         303 :                 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         444 :                 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         299 :                 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         142 :                         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         142 :                                 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         102 :                                 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         426 :                         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           4 :                         request.flags |= WBFLAG_BIG_NTLMV2_BLOB;
     497           4 :                         request.extra_len = params->password.response.nt_length;
     498           4 :                         request.extra_data.data = (char *)malloc(
     499           4 :                                 request.extra_len);
     500           4 :                         if (request.extra_data.data == NULL) {
     501           0 :                                 wbc_status = WBC_ERR_NO_MEMORY;
     502           0 :                                 BAIL_ON_WBC_ERROR(wbc_status);
     503             :                         }
     504           6 :                         memcpy(request.extra_data.data,
     505           4 :                                params->password.response.nt_data,
     506           4 :                                request.data.auth_crap.nt_resp_len);
     507         291 :                 } else if (params->password.response.nt_data) {
     508         430 :                         memcpy(request.data.auth_crap.nt_resp,
     509         283 :                                params->password.response.nt_data,
     510         283 :                                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         308 :                        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        1429 : 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          42 :  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          16 : wbcErr wbcCtxChangeTrustCredentials(struct wbcContext *ctx, const char *domain,
     627             :                                     struct wbcAuthErrorInfo **error)
     628             : {
     629             :         struct winbindd_request request;
     630             :         struct winbindd_response response;
     631          16 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     632             : 
     633          16 :         ZERO_STRUCT(request);
     634          16 :         ZERO_STRUCT(response);
     635             : 
     636          16 :         if (domain) {
     637          16 :                 strncpy(request.domain_name, domain,
     638             :                         sizeof(request.domain_name)-1);
     639             :         }
     640             : 
     641             :         /* Send request */
     642             : 
     643          16 :         wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_CHANGE_MACHACC,
     644             :                                             &request, &response);
     645          16 :         if (response.data.auth.nt_status != 0) {
     646           0 :                 if (error) {
     647           0 :                         wbc_status = wbc_create_error_info(&response,
     648             :                                                            error);
     649           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     650             :                 }
     651             : 
     652           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     653           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     654             :         }
     655          16 :         BAIL_ON_WBC_ERROR(wbc_status);
     656             : 
     657          26 :  done:
     658          16 :         return wbc_status;
     659             : }
     660             : 
     661             : _PUBLIC_
     662          16 : wbcErr wbcChangeTrustCredentials(const char *domain,
     663             :                                  struct wbcAuthErrorInfo **error)
     664             : {
     665          16 :         return wbcCtxChangeTrustCredentials(NULL, domain, error);
     666             : }
     667             : 
     668             : /*
     669             :  * Trigger a no-op NETLOGON call. Lightweight version of
     670             :  * wbcCheckTrustCredentials
     671             :  */
     672             : _PUBLIC_
     673           0 : wbcErr wbcCtxPingDc(struct wbcContext *ctx, const char *domain,
     674             :                     struct wbcAuthErrorInfo **error)
     675             : {
     676           0 :         return wbcCtxPingDc2(ctx, domain, error, NULL);
     677             : }
     678             : 
     679             : _PUBLIC_
     680           8 : wbcErr wbcPingDc(const char *domain, struct wbcAuthErrorInfo **error)
     681             : {
     682           8 :         return wbcPingDc2(domain, error, NULL);
     683             : }
     684             : 
     685             : /*
     686             :  * Trigger a no-op NETLOGON call. Lightweight version of
     687             :  * wbcCheckTrustCredentials, optionally return attempted DC
     688             :  */
     689             : _PUBLIC_
     690         108 : wbcErr wbcCtxPingDc2(struct wbcContext *ctx, const char *domain,
     691             :                      struct wbcAuthErrorInfo **error, char **dcname)
     692             : {
     693             :         struct winbindd_request request;
     694             :         struct winbindd_response response;
     695         108 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     696             : 
     697         108 :         ZERO_STRUCT(request);
     698         108 :         ZERO_STRUCT(response);
     699             : 
     700         108 :         if (domain) {
     701          98 :                 strncpy(request.domain_name, domain,
     702             :                         sizeof(request.domain_name)-1);
     703             :         }
     704             : 
     705             :         /* Send request */
     706             : 
     707         108 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PING_DC,
     708             :                                         &request,
     709             :                                         &response);
     710             : 
     711         108 :         if (dcname && response.extra_data.data) {
     712             :                 size_t len;
     713             : 
     714          88 :                 len = response.length - sizeof(struct winbindd_response);
     715          88 :                 *dcname = wbcAllocateMemory(1, len, NULL);
     716          88 :                 BAIL_ON_PTR_ERROR(*dcname, wbc_status);
     717             : 
     718          88 :                 strlcpy(*dcname, response.extra_data.data, len);
     719             :         }
     720             : 
     721         108 :         if (response.data.auth.nt_status != 0) {
     722           0 :                 if (error) {
     723           0 :                         wbc_status = wbc_create_error_info(&response,
     724             :                                                            error);
     725           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     726             :                 }
     727             : 
     728           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     729           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     730             :         }
     731         115 :         BAIL_ON_WBC_ERROR(wbc_status);
     732             : 
     733         161 :  done:
     734         108 :         winbindd_free_response(&response);
     735         108 :         return wbc_status;
     736             : }
     737             : 
     738             : _PUBLIC_
     739         108 : wbcErr wbcPingDc2(const char *domain, struct wbcAuthErrorInfo **error,
     740             :                   char **dcname)
     741             : {
     742         108 :         return wbcCtxPingDc2(NULL, domain, error, dcname);
     743             : }
     744             : 
     745             : /* Trigger an extended logoff notification to Winbind for a specific user */
     746             : _PUBLIC_
     747           0 : wbcErr wbcCtxLogoffUserEx(struct wbcContext *ctx,
     748             :                           const struct wbcLogoffUserParams *params,
     749             :                           struct wbcAuthErrorInfo **error)
     750             : {
     751             :         struct winbindd_request request;
     752             :         struct winbindd_response response;
     753           0 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     754             :         size_t i;
     755             : 
     756             :         /* validate input */
     757             : 
     758           0 :         if (!params || !params->username) {
     759           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     760           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     761             :         }
     762             : 
     763           0 :         if ((params->num_blobs > 0) && (params->blobs == NULL)) {
     764           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     765           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     766             :         }
     767           0 :         if ((params->num_blobs == 0) && (params->blobs != NULL)) {
     768           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     769           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     770             :         }
     771             : 
     772           0 :         ZERO_STRUCT(request);
     773           0 :         ZERO_STRUCT(response);
     774             : 
     775           0 :         strncpy(request.data.logoff.user, params->username,
     776             :                 sizeof(request.data.logoff.user)-1);
     777             : 
     778           0 :         for (i=0; i<params->num_blobs; i++) {
     779             : 
     780           0 :                 if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) {
     781           0 :                         if (params->blobs[i].blob.data) {
     782           0 :                                 strncpy(request.data.logoff.krb5ccname,
     783           0 :                                         (const char *)params->blobs[i].blob.data,
     784             :                                         sizeof(request.data.logoff.krb5ccname) - 1);
     785             :                         }
     786           0 :                         continue;
     787             :                 }
     788             : 
     789           0 :                 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
     790           0 :                         if (params->blobs[i].blob.data) {
     791           0 :                                 memcpy(&request.data.logoff.uid,
     792           0 :                                         params->blobs[i].blob.data,
     793           0 :                                         MIN(params->blobs[i].blob.length,
     794             :                                             sizeof(request.data.logoff.uid)));
     795             :                         }
     796           0 :                         continue;
     797             :                 }
     798             : 
     799           0 :                 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
     800           0 :                         if (params->blobs[i].blob.data) {
     801           0 :                                 memcpy(&request.flags,
     802           0 :                                         params->blobs[i].blob.data,
     803           0 :                                         MIN(params->blobs[i].blob.length,
     804             :                                             sizeof(request.flags)));
     805             :                         }
     806           0 :                         continue;
     807             :                 }
     808             :         }
     809             : 
     810             :         /* Send request */
     811             : 
     812           0 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_LOGOFF,
     813             :                                         &request,
     814             :                                         &response);
     815             : 
     816             :         /* Take the response above and return it to the caller */
     817           0 :         if (response.data.auth.nt_status != 0) {
     818           0 :                 if (error) {
     819           0 :                         wbc_status = wbc_create_error_info(&response,
     820             :                                                            error);
     821           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     822             :                 }
     823             : 
     824           0 :                 wbc_status = WBC_ERR_AUTH_ERROR;
     825           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     826             :         }
     827           0 :         BAIL_ON_WBC_ERROR(wbc_status);
     828             : 
     829           0 :  done:
     830           0 :         return wbc_status;
     831             : }
     832             : 
     833             : _PUBLIC_
     834           0 : wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params,
     835             :                        struct wbcAuthErrorInfo **error)
     836             : {
     837           0 :         return wbcCtxLogoffUserEx(NULL, params, error);
     838             : }
     839             : 
     840             : /* Trigger a logoff notification to Winbind for a specific user */
     841             : _PUBLIC_
     842           4 : wbcErr wbcCtxLogoffUser(struct wbcContext *ctx,
     843             :                         const char *username, uid_t uid,
     844             :                         const char *ccfilename)
     845             : {
     846             :         struct winbindd_request request;
     847             :         struct winbindd_response response;
     848           4 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     849             : 
     850             :         /* validate input */
     851             : 
     852           4 :         if (!username) {
     853           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     854           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     855             :         }
     856             : 
     857           4 :         ZERO_STRUCT(request);
     858           4 :         ZERO_STRUCT(response);
     859             : 
     860           4 :         strncpy(request.data.logoff.user, username,
     861             :                 sizeof(request.data.logoff.user)-1);
     862           4 :         request.data.logoff.uid = uid;
     863             : 
     864           4 :         if (ccfilename) {
     865           4 :                 strncpy(request.data.logoff.krb5ccname, ccfilename,
     866             :                         sizeof(request.data.logoff.krb5ccname)-1);
     867             :         }
     868             : 
     869             :         /* Send request */
     870             : 
     871           4 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_LOGOFF,
     872             :                                         &request,
     873             :                                         &response);
     874             : 
     875             :         /* Take the response above and return it to the caller */
     876             : 
     877           4 :  done:
     878           4 :         return wbc_status;
     879             : }
     880             : 
     881             : _PUBLIC_
     882           4 : wbcErr wbcLogoffUser(const char *username,
     883             :                      uid_t uid,
     884             :                      const char *ccfilename)
     885             : {
     886           4 :         return wbcCtxLogoffUser(NULL, username, uid, ccfilename);
     887             : }
     888             : 
     889             : /* Change a password for a user with more detailed information upon failure */
     890             : _PUBLIC_
     891          16 : wbcErr wbcCtxChangeUserPasswordEx(struct wbcContext *ctx,
     892             :                         const struct wbcChangePasswordParams *params,
     893             :                         struct wbcAuthErrorInfo **error,
     894             :                         enum wbcPasswordChangeRejectReason *reject_reason,
     895             :                         struct wbcUserPasswordPolicyInfo **policy)
     896             : {
     897             :         struct winbindd_request request;
     898             :         struct winbindd_response response;
     899          16 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     900          16 :         int cmd = 0;
     901             : 
     902             :         /* validate input */
     903             : 
     904          16 :         if (!params->account_name) {
     905           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     906           0 :                 goto done;
     907             :         }
     908             : 
     909          16 :         if (error) {
     910          12 :                 *error = NULL;
     911             :         }
     912             : 
     913          16 :         if (policy) {
     914          12 :                 *policy = NULL;
     915             :         }
     916             : 
     917          16 :         if (reject_reason) {
     918          12 :                 *reject_reason = -1;
     919             :         }
     920             : 
     921          16 :         ZERO_STRUCT(request);
     922          16 :         ZERO_STRUCT(response);
     923             : 
     924          16 :         switch (params->level) {
     925          14 :         case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
     926          14 :                 cmd = WINBINDD_PAM_CHAUTHTOK;
     927             : 
     928          14 :                 if (!params->account_name) {
     929           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     930           0 :                         goto done;
     931             :                 }
     932             : 
     933          14 :                 strncpy(request.data.chauthtok.user, params->account_name,
     934             :                         sizeof(request.data.chauthtok.user) - 1);
     935             : 
     936          14 :                 if (params->old_password.plaintext) {
     937          14 :                         strncpy(request.data.chauthtok.oldpass,
     938           7 :                                 params->old_password.plaintext,
     939             :                                 sizeof(request.data.chauthtok.oldpass) - 1);
     940             :                 }
     941             : 
     942          14 :                 if (params->new_password.plaintext) {
     943          14 :                         strncpy(request.data.chauthtok.newpass,
     944           7 :                                 params->new_password.plaintext,
     945             :                                 sizeof(request.data.chauthtok.newpass) - 1);
     946             :                 }
     947          14 :                 break;
     948             : 
     949           2 :         case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
     950           2 :                 cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
     951             : 
     952           2 :                 if (!params->account_name || !params->domain_name) {
     953           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     954           0 :                         goto done;
     955             :                 }
     956             : 
     957           2 :                 if (params->old_password.response.old_lm_hash_enc_length &&
     958           0 :                     !params->old_password.response.old_lm_hash_enc_data) {
     959           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     960           0 :                         goto done;
     961             :                 }
     962             : 
     963           3 :                 if (params->old_password.response.old_lm_hash_enc_length == 0 &&
     964           2 :                     params->old_password.response.old_lm_hash_enc_data) {
     965           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     966           0 :                         goto done;
     967             :                 }
     968             : 
     969           3 :                 if (params->old_password.response.old_nt_hash_enc_length &&
     970           2 :                     !params->old_password.response.old_nt_hash_enc_data) {
     971           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     972           0 :                         goto done;
     973             :                 }
     974             : 
     975           2 :                 if (params->old_password.response.old_nt_hash_enc_length == 0 &&
     976           0 :                     params->old_password.response.old_nt_hash_enc_data) {
     977           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     978           0 :                         goto done;
     979             :                 }
     980             : 
     981           2 :                 if (params->new_password.response.lm_length &&
     982           0 :                     !params->new_password.response.lm_data) {
     983           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     984           0 :                         goto done;
     985             :                 }
     986             : 
     987           3 :                 if (params->new_password.response.lm_length == 0 &&
     988           2 :                     params->new_password.response.lm_data) {
     989           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     990           0 :                         goto done;
     991             :                 }
     992             : 
     993           3 :                 if (params->new_password.response.nt_length &&
     994           2 :                     !params->new_password.response.nt_data) {
     995           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
     996           0 :                         goto done;
     997             :                 }
     998             : 
     999           2 :                 if (params->new_password.response.nt_length == 0 &&
    1000           0 :                     params->new_password.response.nt_data) {
    1001           0 :                         wbc_status = WBC_ERR_INVALID_PARAM;
    1002           0 :                         goto done;
    1003             :                 }
    1004             : 
    1005           2 :                 strncpy(request.data.chng_pswd_auth_crap.user,
    1006           1 :                         params->account_name,
    1007             :                         sizeof(request.data.chng_pswd_auth_crap.user) - 1);
    1008             : 
    1009           2 :                 strncpy(request.data.chng_pswd_auth_crap.domain,
    1010           1 :                         params->domain_name,
    1011             :                         sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
    1012             : 
    1013           2 :                 if (params->new_password.response.nt_data) {
    1014           2 :                         request.data.chng_pswd_auth_crap.new_nt_pswd_len =
    1015           2 :                                 params->new_password.response.nt_length;
    1016           3 :                         memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
    1017           2 :                                params->new_password.response.nt_data,
    1018           2 :                                request.data.chng_pswd_auth_crap.new_nt_pswd_len);
    1019             :                 }
    1020             : 
    1021           2 :                 if (params->new_password.response.lm_data) {
    1022           0 :                         request.data.chng_pswd_auth_crap.new_lm_pswd_len =
    1023           0 :                                 params->new_password.response.lm_length;
    1024           0 :                         memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
    1025           0 :                                params->new_password.response.lm_data,
    1026           0 :                                request.data.chng_pswd_auth_crap.new_lm_pswd_len);
    1027             :                 }
    1028             : 
    1029           2 :                 if (params->old_password.response.old_nt_hash_enc_data) {
    1030           2 :                         request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
    1031           2 :                                 params->old_password.response.old_nt_hash_enc_length;
    1032           3 :                         memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
    1033           2 :                                params->old_password.response.old_nt_hash_enc_data,
    1034           2 :                                request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
    1035             :                 }
    1036             : 
    1037           2 :                 if (params->old_password.response.old_lm_hash_enc_data) {
    1038           0 :                         request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
    1039           0 :                                 params->old_password.response.old_lm_hash_enc_length;
    1040           0 :                         memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
    1041           0 :                                params->old_password.response.old_lm_hash_enc_data,
    1042           0 :                                request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
    1043             :                 }
    1044             : 
    1045           2 :                 break;
    1046           0 :         default:
    1047           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1048           0 :                 goto done;
    1049             :                 break;
    1050             :         }
    1051             : 
    1052             :         /* Send request */
    1053             : 
    1054          16 :         wbc_status = wbcRequestResponse(ctx, cmd,
    1055             :                                         &request,
    1056             :                                         &response);
    1057          16 :         if (WBC_ERROR_IS_OK(wbc_status)) {
    1058          16 :                 goto done;
    1059             :         }
    1060             : 
    1061             :         /* Take the response above and return it to the caller */
    1062             : 
    1063           0 :         if (response.data.auth.nt_status != 0) {
    1064           0 :                 if (error) {
    1065           0 :                         wbc_status = wbc_create_error_info(&response,
    1066             :                                                            error);
    1067           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
    1068             :                 }
    1069             : 
    1070             :         }
    1071             : 
    1072           0 :         if (policy) {
    1073           0 :                 wbc_status = wbc_create_password_policy_info(&response,
    1074             :                                                              policy);
    1075           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1076             :         }
    1077             : 
    1078           0 :         if (reject_reason) {
    1079           0 :                 *reject_reason = response.data.auth.reject_reason;
    1080             :         }
    1081             : 
    1082           0 :         wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
    1083           0 :         BAIL_ON_WBC_ERROR(wbc_status);
    1084             : 
    1085           8 :  done:
    1086          16 :         return wbc_status;
    1087             : }
    1088             : 
    1089             : _PUBLIC_
    1090           2 : wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
    1091             :                               struct wbcAuthErrorInfo **error,
    1092             :                               enum wbcPasswordChangeRejectReason *reject_reason,
    1093             :                               struct wbcUserPasswordPolicyInfo **policy)
    1094             : {
    1095           2 :         return wbcCtxChangeUserPasswordEx(NULL, params, error,
    1096             :                                           reject_reason, policy);
    1097             : }
    1098             : 
    1099             : /* Change a password for a user */
    1100             : _PUBLIC_
    1101           2 : wbcErr wbcCtxChangeUserPassword(struct wbcContext *ctx,
    1102             :                                 const char *username,
    1103             :                                 const char *old_password,
    1104             :                                 const char *new_password)
    1105             : {
    1106           2 :         wbcErr wbc_status = WBC_ERR_SUCCESS;
    1107             :         struct wbcChangePasswordParams params;
    1108             : 
    1109           2 :         ZERO_STRUCT(params);
    1110             : 
    1111           2 :         params.account_name             = username;
    1112           2 :         params.level                    = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
    1113           2 :         params.old_password.plaintext   = old_password;
    1114           2 :         params.new_password.plaintext   = new_password;
    1115             : 
    1116           2 :         wbc_status = wbcCtxChangeUserPasswordEx(ctx, &params,
    1117             :                                                 NULL,
    1118             :                                                 NULL,
    1119             :                                                 NULL);
    1120           2 :         BAIL_ON_WBC_ERROR(wbc_status);
    1121             : 
    1122           3 : done:
    1123           2 :         return wbc_status;
    1124             : }
    1125             : 
    1126             : _PUBLIC_
    1127           2 : wbcErr wbcChangeUserPassword(const char *username,
    1128             :                              const char *old_password,
    1129             :                              const char *new_password)
    1130             : {
    1131           2 :         return wbcCtxChangeUserPassword(NULL, username,
    1132             :                                         old_password, new_password);
    1133             : }
    1134             : 
    1135             : /* Logon a User */
    1136             : _PUBLIC_
    1137         326 : wbcErr wbcCtxLogonUser(struct wbcContext *ctx,
    1138             :                        const struct wbcLogonUserParams *params,
    1139             :                        struct wbcLogonUserInfo **info,
    1140             :                        struct wbcAuthErrorInfo **error,
    1141             :                        struct wbcUserPasswordPolicyInfo **policy)
    1142             : {
    1143         326 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
    1144             :         struct winbindd_request request;
    1145             :         struct winbindd_response response;
    1146             :         uint32_t i;
    1147             : 
    1148         326 :         ZERO_STRUCT(request);
    1149         326 :         ZERO_STRUCT(response);
    1150             : 
    1151         326 :         if (info) {
    1152         326 :                 *info = NULL;
    1153             :         }
    1154         326 :         if (error) {
    1155         326 :                 *error = NULL;
    1156             :         }
    1157         326 :         if (policy) {
    1158          54 :                 *policy = NULL;
    1159             :         }
    1160             : 
    1161         326 :         if (!params) {
    1162           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1163           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1164             :         }
    1165             : 
    1166         326 :         if (!params->username) {
    1167           2 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1168           2 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1169             :         }
    1170             : 
    1171         324 :         if ((params->num_blobs > 0) && (params->blobs == NULL)) {
    1172           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1173           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1174             :         }
    1175         324 :         if ((params->num_blobs == 0) && (params->blobs != NULL)) {
    1176           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1177           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1178             :         }
    1179             : 
    1180             :         /* Initialize request */
    1181             : 
    1182         324 :         request.flags = WBFLAG_PAM_INFO3_TEXT |
    1183             :                         WBFLAG_PAM_USER_SESSION_KEY |
    1184             :                         WBFLAG_PAM_LMKEY;
    1185             : 
    1186         324 :         if (!params->password) {
    1187           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
    1188           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1189             :         }
    1190             : 
    1191         324 :         strncpy(request.data.auth.user,
    1192         160 :                 params->username,
    1193             :                 sizeof(request.data.auth.user)-1);
    1194             : 
    1195         324 :         strncpy(request.data.auth.pass,
    1196         160 :                 params->password,
    1197             :                 sizeof(request.data.auth.pass)-1);
    1198             : 
    1199        1124 :         for (i=0; i<params->num_blobs; i++) {
    1200             : 
    1201         800 :                 if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) {
    1202         160 :                         if (params->blobs[i].blob.data) {
    1203         160 :                                 strncpy(request.data.auth.krb5_cc_type,
    1204         160 :                                         (const char *)params->blobs[i].blob.data,
    1205             :                                         sizeof(request.data.auth.krb5_cc_type) - 1);
    1206             :                         }
    1207         160 :                         continue;
    1208             :                 }
    1209             : 
    1210         640 :                 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
    1211         314 :                         if (params->blobs[i].blob.data) {
    1212         314 :                                 memcpy(&request.data.auth.uid,
    1213         314 :                                         params->blobs[i].blob.data,
    1214         314 :                                         MIN(sizeof(request.data.auth.uid),
    1215             :                                             params->blobs[i].blob.length));
    1216             :                         }
    1217         314 :                         continue;
    1218             :                 }
    1219             : 
    1220         326 :                 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
    1221         316 :                         if (params->blobs[i].blob.data) {
    1222             :                                 uint32_t flags;
    1223         316 :                                 memcpy(&flags,
    1224         316 :                                         params->blobs[i].blob.data,
    1225         316 :                                         MIN(sizeof(flags),
    1226             :                                             params->blobs[i].blob.length));
    1227         316 :                                 request.flags |= flags;
    1228             :                         }
    1229         316 :                         continue;
    1230             :                 }
    1231             : 
    1232          10 :                 if (strcasecmp(params->blobs[i].name, "membership_of") == 0) {
    1233           6 :                         if (params->blobs[i].blob.data &&
    1234           4 :                             params->blobs[i].blob.data[0] > 0) {
    1235           4 :                                 strncpy(request.data.auth.require_membership_of_sid,
    1236           4 :                                         (const char *)params->blobs[i].blob.data,
    1237             :                                         sizeof(request.data.auth.require_membership_of_sid) - 1);
    1238             :                         }
    1239           4 :                         continue;
    1240             :                 }
    1241             :         }
    1242             : 
    1243         324 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_PAM_AUTH,
    1244             :                                         &request,
    1245             :                                         &response);
    1246             : 
    1247         324 :         if (response.data.auth.nt_status != 0) {
    1248          94 :                 if (error) {
    1249          94 :                         wbc_status = wbc_create_error_info(&response,
    1250             :                                                            error);
    1251          94 :                         BAIL_ON_WBC_ERROR(wbc_status);
    1252             :                 }
    1253             : 
    1254          94 :                 wbc_status = WBC_ERR_AUTH_ERROR;
    1255          94 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1256             :         }
    1257         230 :         BAIL_ON_WBC_ERROR(wbc_status);
    1258             : 
    1259         230 :         if (info) {
    1260         230 :                 wbc_status = wbc_create_logon_info(&response,
    1261             :                                                    info);
    1262         230 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1263             :         }
    1264             : 
    1265         230 :         if (policy) {
    1266          42 :                 wbc_status = wbc_create_password_policy_info(&response,
    1267             :                                                              policy);
    1268          42 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1269             :         }
    1270             : 
    1271         395 : done:
    1272         326 :         winbindd_free_response(&response);
    1273             : 
    1274         326 :         return wbc_status;
    1275             : }
    1276             : 
    1277             : _PUBLIC_
    1278          78 : wbcErr wbcLogonUser(const struct wbcLogonUserParams *params,
    1279             :                     struct wbcLogonUserInfo **info,
    1280             :                     struct wbcAuthErrorInfo **error,
    1281             :                     struct wbcUserPasswordPolicyInfo **policy)
    1282             : {
    1283          78 :         return wbcCtxLogonUser(NULL, params, info, error, policy);
    1284             : }
    1285             : 
    1286          16 : static void wbcCredentialCacheInfoDestructor(void *ptr)
    1287             : {
    1288          16 :         struct wbcCredentialCacheInfo *i =
    1289             :                 (struct wbcCredentialCacheInfo *)ptr;
    1290          16 :         wbcFreeMemory(i->blobs);
    1291          16 : }
    1292             : 
    1293             : /* Authenticate a user with cached credentials */
    1294             : _PUBLIC_
    1295          16 : wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
    1296             :                              struct wbcCredentialCacheParams *params,
    1297             :                              struct wbcCredentialCacheInfo **info,
    1298             :                              struct wbcAuthErrorInfo **error)
    1299             : {
    1300          16 :         wbcErr status = WBC_ERR_UNKNOWN_FAILURE;
    1301          16 :         struct wbcCredentialCacheInfo *result = NULL;
    1302             :         struct winbindd_request request;
    1303             :         struct winbindd_response response;
    1304          16 :         struct wbcNamedBlob *initial_blob = NULL;
    1305          16 :         struct wbcNamedBlob *challenge_blob = NULL;
    1306             :         size_t i;
    1307             : 
    1308          16 :         ZERO_STRUCT(request);
    1309          16 :         ZERO_STRUCT(response);
    1310             : 
    1311          16 :         *info = NULL;
    1312             : 
    1313          16 :         if (error != NULL) {
    1314          16 :                 *error = NULL;
    1315             :         }
    1316          16 :         if ((params == NULL)
    1317          16 :             || (params->account_name == NULL)
    1318          16 :             || (params->level != WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP)) {
    1319           0 :                 status = WBC_ERR_INVALID_PARAM;
    1320           0 :                 goto fail;
    1321             :         }
    1322             : 
    1323          40 :         for (i=0; i<params->num_blobs; i++) {
    1324             :                 /*
    1325             :                  * Older callers may used to provide the NEGOTIATE request
    1326             :                  * as "initial_blob", but it was completely ignored by winbindd.
    1327             :                  *
    1328             :                  * So we keep ignoring it.
    1329             :                  *
    1330             :                  * A new callers that is capable to support "new_spnego",
    1331             :                  * will provide the NEGOTIATE request as "negotiate_blob"
    1332             :                  * instead.
    1333             :                  */
    1334          24 :                 if (strcasecmp(params->blobs[i].name, "negotiate_blob") == 0) {
    1335          12 :                         if (initial_blob != NULL) {
    1336           0 :                                 status = WBC_ERR_INVALID_PARAM;
    1337           0 :                                 goto fail;
    1338             :                         }
    1339          12 :                         initial_blob = &params->blobs[i];
    1340          12 :                         continue;
    1341             :                 }
    1342          12 :                 if (strcasecmp(params->blobs[i].name, "challenge_blob") == 0) {
    1343          12 :                         if (challenge_blob != NULL) {
    1344           0 :                                 status = WBC_ERR_INVALID_PARAM;
    1345           0 :                                 goto fail;
    1346             :                         }
    1347          12 :                         challenge_blob = &params->blobs[i];
    1348          12 :                         continue;
    1349             :                 }
    1350             :         }
    1351             : 
    1352          16 :         if (params->domain_name != NULL) {
    1353          16 :                 status = wbcRequestResponse(ctx, WINBINDD_INFO,
    1354             :                                             NULL, &response);
    1355          16 :                 if (!WBC_ERROR_IS_OK(status)) {
    1356           0 :                         goto fail;
    1357             :                 }
    1358          26 :                 snprintf(request.data.ccache_ntlm_auth.user,
    1359             :                          sizeof(request.data.ccache_ntlm_auth.user)-1,
    1360             :                          "%s%c%s", params->domain_name,
    1361          16 :                          response.data.info.winbind_separator,
    1362             :                          params->account_name);
    1363             :         } else {
    1364           0 :                 strncpy(request.data.ccache_ntlm_auth.user,
    1365             :                         params->account_name,
    1366             :                         sizeof(request.data.ccache_ntlm_auth.user)-1);
    1367             :         }
    1368          16 :         request.data.ccache_ntlm_auth.uid = getuid();
    1369             : 
    1370          16 :         request.data.ccache_ntlm_auth.initial_blob_len = 0;
    1371          16 :         request.data.ccache_ntlm_auth.challenge_blob_len = 0;
    1372          16 :         request.extra_len = 0;
    1373             : 
    1374          16 :         if (initial_blob != NULL) {
    1375          12 :                 request.data.ccache_ntlm_auth.initial_blob_len =
    1376          12 :                         initial_blob->blob.length;
    1377          12 :                 request.extra_len += initial_blob->blob.length;
    1378             :         }
    1379          16 :         if (challenge_blob != NULL) {
    1380          12 :                 request.data.ccache_ntlm_auth.challenge_blob_len =
    1381          12 :                         challenge_blob->blob.length;
    1382          12 :                 request.extra_len += challenge_blob->blob.length;
    1383             :         }
    1384             : 
    1385          16 :         if (request.extra_len != 0) {
    1386          12 :                 request.extra_data.data = (char *)malloc(request.extra_len);
    1387          12 :                 if (request.extra_data.data == NULL) {
    1388           0 :                         status = WBC_ERR_NO_MEMORY;
    1389           0 :                         goto fail;
    1390             :                 }
    1391             :         }
    1392          16 :         if (initial_blob != NULL) {
    1393          19 :                 memcpy(request.extra_data.data,
    1394          12 :                        initial_blob->blob.data, initial_blob->blob.length);
    1395             :         }
    1396          16 :         if (challenge_blob != NULL) {
    1397          26 :                 memcpy(request.extra_data.data
    1398          12 :                        + request.data.ccache_ntlm_auth.initial_blob_len,
    1399          12 :                        challenge_blob->blob.data,
    1400             :                        challenge_blob->blob.length);
    1401             :         }
    1402             : 
    1403          16 :         status = wbcRequestResponse(ctx, WINBINDD_CCACHE_NTLMAUTH,
    1404             :                                     &request, &response);
    1405          16 :         if (!WBC_ERROR_IS_OK(status)) {
    1406           0 :                 goto fail;
    1407             :         }
    1408             : 
    1409          16 :         result = (struct wbcCredentialCacheInfo *)wbcAllocateMemory(
    1410             :                 1, sizeof(struct wbcCredentialCacheInfo),
    1411             :                 wbcCredentialCacheInfoDestructor);
    1412          16 :         if (result == NULL) {
    1413           0 :                 status = WBC_ERR_NO_MEMORY;
    1414           0 :                 goto fail;
    1415             :         }
    1416          16 :         result->num_blobs = 0;
    1417          16 :         result->blobs = NULL;
    1418          26 :         status = wbcAddNamedBlob(&result->num_blobs, &result->blobs,
    1419             :                                  "auth_blob", 0,
    1420          16 :                                  (uint8_t *)response.extra_data.data,
    1421          16 :                                  response.data.ccache_ntlm_auth.auth_blob_len);
    1422          16 :         if (!WBC_ERROR_IS_OK(status)) {
    1423           0 :                 goto fail;
    1424             :         }
    1425          16 :         status = wbcAddNamedBlob(
    1426             :                 &result->num_blobs, &result->blobs, "session_key", 0,
    1427             :                 response.data.ccache_ntlm_auth.session_key,
    1428             :                 sizeof(response.data.ccache_ntlm_auth.session_key));
    1429          16 :         if (!WBC_ERROR_IS_OK(status)) {
    1430           0 :                 goto fail;
    1431             :         }
    1432          16 :         if (response.data.ccache_ntlm_auth.new_spnego) {
    1433           8 :                 status = wbcAddNamedBlob(
    1434             :                         &result->num_blobs, &result->blobs, "new_spnego", 0,
    1435             :                         &response.data.ccache_ntlm_auth.new_spnego,
    1436             :                         sizeof(response.data.ccache_ntlm_auth.new_spnego));
    1437           8 :                 if (!WBC_ERROR_IS_OK(status)) {
    1438           0 :                         goto fail;
    1439             :                 }
    1440             :         }
    1441             : 
    1442          16 :         *info = result;
    1443          16 :         result = NULL;
    1444          16 :         status = WBC_ERR_SUCCESS;
    1445          16 : fail:
    1446          16 :         free(request.extra_data.data);
    1447          16 :         winbindd_free_response(&response);
    1448          16 :         wbcFreeMemory(result);
    1449          16 :         return status;
    1450             : }
    1451             : 
    1452             : _PUBLIC_
    1453          16 : wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
    1454             :                           struct wbcCredentialCacheInfo **info,
    1455             :                           struct wbcAuthErrorInfo **error)
    1456             : {
    1457          16 :         return wbcCtxCredentialCache(NULL, params, info, error);
    1458             : }
    1459             : 
    1460             : /* Authenticate a user with cached credentials */
    1461             : _PUBLIC_
    1462          24 : wbcErr wbcCtxCredentialSave(struct wbcContext *ctx,
    1463             :                             const char *user, const char *password)
    1464             : {
    1465             :         struct winbindd_request request;
    1466             :         struct winbindd_response response;
    1467             : 
    1468          24 :         ZERO_STRUCT(request);
    1469          24 :         ZERO_STRUCT(response);
    1470             : 
    1471          24 :         strncpy(request.data.ccache_save.user, user,
    1472             :                 sizeof(request.data.ccache_save.user)-1);
    1473          24 :         strncpy(request.data.ccache_save.pass, password,
    1474             :                 sizeof(request.data.ccache_save.pass)-1);
    1475          24 :         request.data.ccache_save.uid = getuid();
    1476             : 
    1477          24 :         return wbcRequestResponse(ctx, WINBINDD_CCACHE_SAVE, &request, &response);
    1478             : }
    1479             : 
    1480             : _PUBLIC_
    1481          24 : wbcErr wbcCredentialSave(const char *user, const char *password)
    1482             : {
    1483          24 :         return wbcCtxCredentialSave(NULL, user, password);
    1484             : }

Generated by: LCOV version 1.13