/* ======================================================================== * Copyright 2018-2021 Eduardo Chappa * Copyright 2015 Imagination Technologies * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * * ======================================================================== */ /* * Program: NT LAN Manager authenticator * * Author: Maciej W. Rozycki * * Date: 25 January 2015 * Last Edited: 25 January 2015 */ #include long auth_ntlm_client (authchallenge_t challenger,authrespond_t responder,char *base, char *service,NETMBX *mb,void *stream, unsigned long port, unsigned long *trial,char *user); AUTHENTICATOR auth_ntl = { /* secure, has full auth, hidden */ AU_SECURE | AU_AUTHUSER | AU_HIDE, "NTLM", /* authenticator name */ NIL, /* always valid */ auth_ntlm_client, /* client method */ NIL, /* no server method */ NIL /* next authenticator */ }; /* Client authenticator * Accepts: challenger function * responder function * SASL service name * parsed network mailbox structure * stream argument for functions * pointer to current trial count * returned user name * Returns: T if success, NIL otherwise, number of trials incremented if retry */ long auth_ntlm_client (authchallenge_t challenger, authrespond_t responder,char *base, char *service, NETMBX *mb, void *stream, unsigned long port, unsigned long *trial, char *user) { tSmbNtlmAuthChallenge *challenge; tSmbNtlmAuthResponse response; tSmbNtlmAuthRequest request; char tbuf[MAILTMPLEN]; char ubuf[MAILTMPLEN]; char *pass = NIL; unsigned long clen; unsigned long ulen; unsigned long dlen; long ret = NIL; char *sep; /* get initial (empty) challenge */ if (challenge = (*challenger) (stream, &clen)) { fs_give ((void **) &challenge); mm_login (mb, user, &pass, *trial); if (!pass) { /* user requested abort */ (*responder) (stream, base, NIL, 0); *trial = 0; /* cancel subsequent attempts */ ret = LONGT; /* will get a BAD response back */ } else { /* translate domain\user to user@domain */ /* otherwise buildSmbNtlmAuthResponse */ /* will override the domain requested with */ /* one returned by the challenge message */ sep = strchr (user, '\\'); if (sep) { dlen = sep - user; ulen = strlen (sep + 1); memcpy (ubuf, sep + 1, ulen); ubuf[ulen] = '@'; memcpy (ubuf + ulen + 1, user, dlen); ubuf[ulen + dlen + 1] = '\0'; user = ubuf; } buildSmbNtlmAuthRequest (&request, user, NULL); /* send a negotiate message */ if ((*responder) (stream, base, (void *) &request, SmbLength (&request)) && (challenge = (*challenger) (stream, &clen))) { /* interpret the challenge message */ buildSmbNtlmAuthResponse (challenge, &response, user, pass); fs_give ((void **) &challenge); /* send a response message */ if ((*responder) (stream, base, (void *) &response, SmbLength (&response))) { if (challenge = (*challenger) (stream, &clen)) fs_give ((void **) &challenge); else { ++*trial; /* can try again if necessary */ ret = LONGT; /* check the authentication */ } } } if(pass) fs_give((void **) &pass); } } if(pass) fs_give((void **) &pass); if (!ret) *trial = 65535; /* don't retry if bad protocol */ return ret; }