X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fplugins%2Fwinbind.c;h=0c395c34711af6cef39d3ac01e3603f7205ebbc5;hp=1abe437a806410888f8d9a2096a5700a05b292a3;hb=c319558b8cacad7d27f04c7d612e44b67f273434;hpb=af32d6370eba9545f813546a7902575d834a0f85 diff --git a/pppd/plugins/winbind.c b/pppd/plugins/winbind.c index 1abe437..0c395c3 100644 --- a/pppd/plugins/winbind.c +++ b/pppd/plugins/winbind.c @@ -61,9 +61,30 @@ 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 @@ -188,42 +209,33 @@ static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01 **/ 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, @@ -257,72 +269,50 @@ 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 */ @@ -442,6 +432,7 @@ unsigned int run_ntlm_auth(const char *username, /* parent */ if (close(child_out[0]) == -1) { + close(child_in[1]); notice("error closing pipe?!? for child OUT[0]"); return NOT_AUTHENTICATED; } @@ -452,7 +443,7 @@ unsigned int run_ntlm_auth(const char *username, return NOT_AUTHENTICATED; } - while ((wait(&status) == -1) && errno == EINTR) + while ((wait(&status) == -1) && errno == EINTR && !got_sigterm) ; if ((authenticated == AUTHENTICATED) && nt_key && !got_user_session_key) { @@ -467,7 +458,7 @@ unsigned int run_ntlm_auth(const char *username, * %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 @@ -475,7 +466,7 @@ unsigned int run_ntlm_auth(const char *username, static int winbind_secret_check(void) { - return 1; + return ntlm_auth != NULL; } /********************************************************************** @@ -561,20 +552,19 @@ winbind_chap_verify(char *user, char *ourname, int id, 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"); @@ -588,12 +578,9 @@ winbind_chap_verify(char *user, char *ourname, int id, 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); @@ -614,7 +601,6 @@ winbind_chap_verify(char *user, char *ourname, int id, 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; @@ -622,7 +608,8 @@ winbind_chap_verify(char *user, char *ourname, int id, 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 */ @@ -630,22 +617,20 @@ winbind_chap_verify(char *user, char *ourname, int id, 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",