static char *ntlm_auth = NULL;
+static int set_ntlm_auth(char **argv)
+{
+ char *p;
+
+ p = argv[0];
+ if (p[0] != '/') {
+ option_error("ntlm_auth-helper argument must be full path");
+ return 0;
+ }
+ p = strdup(p);
+ if (p == NULL) {
+ novm("ntlm_auth-helper argument");
+ return 0;
+ }
+ if (ntlm_auth != NULL)
+ free(ntlm_auth);
+ ntlm_auth = p;
+ return 1;
+}
+
static option_t Options[] = {
- { "ntlm_auth-helper", o_string, &ntlm_auth },
- { NULL }
+ { "ntlm_auth-helper", o_special, (void *) &set_ntlm_auth,
+ "Path to ntlm_auth executable", OPT_PRIV },
+ { NULL }
};
static int
**/
char * base64_encode(const char *data)
{
- int bits = 0;
- int char_count = 0;
size_t out_cnt = 0;
size_t len = strlen(data);
- size_t output_len = strlen(data) * 2;
+ size_t output_len = 4 * ((len + 2) / 3) + 2;
+ const unsigned char *ptr = (const unsigned char *) data;
char *result = malloc(output_len); /* get us plenty of space */
-
- while (len-- && out_cnt < (output_len) - 5) {
- int c = (unsigned char) *(data++);
- bits += c;
- char_count++;
- if (char_count == 3) {
- result[out_cnt++] = b64[bits >> 18];
- result[out_cnt++] = b64[(bits >> 12) & 0x3f];
- result[out_cnt++] = b64[(bits >> 6) & 0x3f];
- result[out_cnt++] = b64[bits & 0x3f];
- bits = 0;
- char_count = 0;
- } else {
- bits <<= 8;
+ unsigned int bits;
+
+ for (; len >= 3; len -= 3) {
+ bits = (ptr[0] << 16) + (ptr[1] << 8) + ptr[2];
+ ptr += 3;
+ result[out_cnt++] = b64[bits >> 18];
+ result[out_cnt++] = b64[(bits >> 12) & 0x3f];
+ result[out_cnt++] = b64[(bits >> 6) & 0x3f];
+ result[out_cnt++] = b64[bits & 0x3f];
}
- }
- if (char_count != 0) {
- bits <<= 16 - (8 * char_count);
- result[out_cnt++] = b64[bits >> 18];
- result[out_cnt++] = b64[(bits >> 12) & 0x3f];
- if (char_count == 1) {
- result[out_cnt++] = '=';
- result[out_cnt++] = '=';
- } else {
- result[out_cnt++] = b64[(bits >> 6) & 0x3f];
- result[out_cnt++] = '=';
+ if (len != 0) {
+ bits = ptr[0] << 16;
+ if (len > 1)
+ bits |= ptr[1] << 8;
+ result[out_cnt++] = b64[bits >> 18];
+ result[out_cnt++] = b64[(bits >> 12) & 0x3f];
+ result[out_cnt++] = (len > 1)? b64[(bits >> 6) & 0x3f]: '=';
+ result[out_cnt++] = '=';
}
- }
- result[out_cnt] = '\0'; /* terminate */
- return result;
+
+ result[out_cnt] = '\0'; /* terminate */
+ return result;
}
unsigned int run_ntlm_auth(const char *username,
char *challenge_hex;
char *lm_hex_hash;
char *nt_hex_hash;
-
+
+ /* First see if we have a program to run... */
+ if (ntlm_auth == NULL)
+ return NOT_AUTHENTICATED;
+
/* Make first child */
if (pipe(child_out) == -1) {
- perror("pipe creation failed for child OUT!");
+ error("pipe creation failed for child OUT!");
+ return NOT_AUTHENTICATED;
}
if (pipe(child_in) == -1) {
- perror("pipe creation failed for child IN!");
+ error("pipe creation failed for child IN!");
+ return NOT_AUTHENTICATED;
}
- forkret = fork();
+ forkret = safe_fork(child_in[0], child_out[1], 2);
if (forkret == -1) {
- perror("fork failed!");
if (error_string) {
*error_string = strdup("fork failed!");
}
return NOT_AUTHENTICATED;
- } else if (forkret == 0) {
- /* child - pipe out */
- if (close(child_out[0]) == -1) {
- perror("error closing pipe?!? for child OUT[READFD]");
- exit(1);
- }
- if (dup2(child_out[1], 1) == -1) {
- perror("(child) dup2 of fdout onto STDOUT failed!");
- }
-
- /* Close extra copies */
- if (close(child_out[1]) == -1) {
- perror("error closing pipe?!? for child OUT[WRITEFD]");
- exit(1);
- }
-
- /* child - pipe in */
- if (close(child_in[1]) == -1) {
- perror("error closing pipe?!? for child IN[WRITEFD]");
- exit(1);
- }
- if (dup2(child_in[0], 0) == -1) {
- perror("(child) dup2 of fdin onto STDIN failed!");
- }
-
- /* Close extra copies */
- if (close(child_in[0]) == -1) {
- perror("error closing pipe?!? for child IN[READFD]");
- exit(1);
- }
+ }
- execl("/bin/sh","sh","-c", ntlm_auth,NULL);
+ if (forkret == 0) {
+ /* child process */
+ uid_t uid;
- /* Not reached... */
- exit(1);
+ close(child_out[0]);
+ close(child_in[1]);
+ /* run winbind as the user that invoked pppd */
+ setgid(getgid());
+ uid = getuid();
+ if (setuid(uid) == -1 || getuid() != uid)
+ fatal("pppd/winbind: could not setuid to %d: %m", uid);
+ execl("/bin/sh", "sh", "-c", ntlm_auth, NULL);
+ fatal("pppd/winbind: could not exec /bin/sh: %m");
}
/* parent */
- if (close(child_out[1]) == -1) {
- notice("error closing pipe?!? for child OUT[1]");
- return NOT_AUTHENTICATED;
- }
-
- if (close(child_in[0]) == -1) {
- notice("error closing pipe?!? for child OUT[1]");
- return NOT_AUTHENTICATED;
- }
+ close(child_out[1]);
+ close(child_in[0]);
/* Need to write the User's info onto the pipe */
* %ARGUMENTS:
* None
* %RETURNS:
-* 1 -- we are ALWAYS willing to supply a secret. :-)
+* 0 if we don't have an ntlm_auth program to run, otherwise 1.
* %DESCRIPTION:
* Tells pppd that we will try to authenticate the peer, and not to
* worry about looking in /etc/ppp/ *-secrets
static int
winbind_secret_check(void)
{
- return 1;
+ return ntlm_auth != NULL;
}
/**********************************************************************
u_char *lm_response = NULL;
int nt_response_size = 0;
int lm_response_size = 0;
- MS_ChapResponse *rmd = (MS_ChapResponse *) response;
u_char session_key[16];
if (response_len != MS_CHAP_RESPONSE_LEN)
break; /* not even the right length */
/* Determine which part of response to verify against */
- if (rmd->UseNT[0]) {
- nt_response = rmd->NTResp;
- nt_response_size = sizeof(rmd->NTResp);
+ if (response[MS_CHAP_USENT]) {
+ nt_response = &response[MS_CHAP_NTRESP];
+ nt_response_size = MS_CHAP_NTRESP_LEN;
} else {
#ifdef MSLANMAN
- lm_response = rmd->LANManResp;
- lm_response_size = sizeof(rmd->LANManResp);
+ lm_response = &response[MS_CHAP_LANMANRESP];
+ lm_response_size = MS_CHAP_LANMANRESP_LEN;
#else
/* Should really propagate this into the error packet. */
notice("Peer request for LANMAN auth not supported");
domain,
NULL,
NULL,
- challenge,
- challenge_len,
- lm_response,
- lm_response ? lm_response_size: 0,
- nt_response,
- nt_response ? nt_response_size: 0,
+ challenge, challenge_len,
+ lm_response, lm_response_size,
+ nt_response, nt_response_size,
session_key,
&error_string) == AUTHENTICATED) {
mppe_set_keys(challenge, session_key);
case CHAP_MICROSOFT_V2:
{
- MS_Chap2Response *rmd = (MS_Chap2Response *) response;
u_char Challenge[8];
u_char session_key[MD4_SIGNATURE_SIZE];
char *error_string = NULL;
if (response_len != MS_CHAP2_RESPONSE_LEN)
break; /* not even the right length */
- ChallengeHash(rmd->PeerChallenge, challenge, user, Challenge);
+ ChallengeHash(&response[MS_CHAP2_PEER_CHALLENGE], challenge,
+ user, Challenge);
/* ship off to winbind, and check */
domain,
NULL,
NULL,
- Challenge,
- 8,
- NULL,
- 0,
- rmd->NTResp,
- sizeof(rmd->NTResp),
-
+ Challenge, 8,
+ NULL, 0,
+ &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_NTRESP_LEN,
session_key,
&error_string) == AUTHENTICATED) {
GenerateAuthenticatorResponse(session_key,
- rmd->NTResp, rmd->PeerChallenge,
- challenge, user,
- saresponse);
- mppe_set_keys2(session_key, rmd->NTResp, MS_CHAP2_AUTHENTICATOR);
- if (rmd->Flags[0]) {
+ &response[MS_CHAP2_NTRESP],
+ &response[MS_CHAP2_PEER_CHALLENGE],
+ challenge, user, saresponse);
+ mppe_set_keys2(session_key, &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_AUTHENTICATOR);
+ if (response[MS_CHAP2_FLAGS]) {
slprintf(message, message_space, "S=%s", saresponse);
} else {
slprintf(message, message_space, "S=%s M=%s",