]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/plugins/winbind.c
pppd.8: Document netmask option
[ppp.git] / pppd / plugins / winbind.c
index 3041f17af8f496a352627f6d28931a434623ec86..7f930dfc2ce493ef9f1a825a365eb0f2e6dbc7c2 100644 (file)
 *
 ***********************************************************************/
 
-#include "pppd.h"
-#include "chap-new.h"
-#include "chap_ms.h"
-#ifdef MPPE
-#include "md5.h"
-#endif
-#include "fsm.h"
-#include "ipcp.h"
 #include <syslog.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <ctype.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <pppd/pppd.h>
+#include <pppd/options.h>
+#include <pppd/chap.h>
+#include <pppd/chap_ms.h>
+#include <pppd/upap.h>
+#include <pppd/fsm.h>
+#include <pppd/ipcp.h>
+#include <pppd/mppe.h>
+#include <pppd/crypto.h>
 
 #define BUF_LEN 1024
 
@@ -67,7 +73,7 @@ static int set_ntlm_auth(char **argv)
 
        p = argv[0];
        if (p[0] != '/') {
-               option_error("ntlm_auth-helper argument must be full path");
+               ppp_option_error("ntlm_auth-helper argument must be full path");
                return 0;
        }
        p = strdup(p);
@@ -81,28 +87,18 @@ static int set_ntlm_auth(char **argv)
        return 1;
 }
 
-static option_t Options[] = {
+static struct option Options[] = {
        { "ntlm_auth-helper", o_special, (void *) &set_ntlm_auth,
          "Path to ntlm_auth executable", OPT_PRIV },
        { NULL }
 };
 
-static int
-winbind_secret_check(void);
-
-static int winbind_pap_auth(char *user,
-                          char *passwd,
-                          char **msgp,
-                          struct wordlist **paddrs,
-                          struct wordlist **popts);
-static int winbind_chap_verify(char *user, char *ourname, int id,
-                              struct chap_digest_type *digest,
-                              unsigned char *challenge,
-                              unsigned char *response,
-                              char *message, int message_space);
-static int winbind_allowed_address(u_int32_t addr); 
-
-char pppd_version[] = VERSION;
+static pap_check_hook_fn winbind_secret_check;
+static pap_auth_hook_fn winbind_pap_auth;
+static chap_verify_hook_fn winbind_chap_verify;
+static int winbind_allowed_address(uint32_t addr);
+
+char pppd_version[] = PPPD_VERSION;
 
 /**********************************************************************
 * %FUNCTION: plugin_init
@@ -127,7 +123,7 @@ plugin_init(void)
     /* Don't ask the peer for anything other than MS-CHAP or MS-CHAP V2 */
     chap_mdtype_all &= (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT);
     
-    add_options(Options);
+    ppp_add_options(Options);
 
     info("WINBIND plugin initialized.");
 }
@@ -165,7 +161,7 @@ plugin_init(void)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-size_t strhex_to_str(char *p, size_t len, const char *strhex)
+size_t strhex_to_str(unsigned char *p, size_t len, const char *strhex)
 {
        size_t i;
        size_t num_chars = 0;
@@ -209,42 +205,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, 
@@ -294,7 +281,7 @@ unsigned int run_ntlm_auth(const char *username,
                return NOT_AUTHENTICATED;
         }
 
-        forkret = safe_fork(child_in[0], child_out[1], 2);
+        forkret = ppp_safe_fork(child_in[0], child_out[1], 2);
         if (forkret == -1) {
                if (error_string) {
                        *error_string = strdup("fork failed!");
@@ -305,15 +292,23 @@ unsigned int run_ntlm_auth(const char *username,
 
        if (forkret == 0) {
                /* child process */
+               uid_t uid;
+               gid_t gid;
+
                close(child_out[0]);
                close(child_in[1]);
 
                /* run winbind as the user that invoked pppd */
-               setgid(getgid());
-               setuid(getuid());
+               gid = getgid();
+               if (setgid(gid) == -1 || getgid() != gid) {
+                       fatal("pppd/winbind: could not setgid to %d: %m", gid);
+               }
+               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);  
-               perror("pppd/winbind: could not exec /bin/sh");
-               exit(1);
+               fatal("pppd/winbind: could not exec /bin/sh: %m");
        }
 
         /* parent */
@@ -438,6 +433,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;
         }
@@ -448,7 +444,7 @@ unsigned int run_ntlm_auth(const char *username,
                 return NOT_AUTHENTICATED;
         }
 
-       while ((wait(&status) == -1) && errno == EINTR)
+       while ((wait(&status) == -1) && errno == EINTR && !ppp_signaled(SIGTERM))
                 ;
 
        if ((authenticated == AUTHENTICATED) && nt_key && !got_user_session_key) {
@@ -523,9 +519,9 @@ winbind_chap_verify(char *user, char *ourname, int id,
        int challenge_len, response_len;
        char domainname[256];
        char *domain;
-       char *username;
+       const char *username;
        char *p;
-       char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
+       unsigned char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
 
        /* The first byte of each of these strings contains their length */
        challenge_len = *challenge++;
@@ -557,25 +553,24 @@ 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];
+               u_char session_key[MD4_DIGEST_LENGTH];
                
                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);
+#ifdef PPP_WITH_MSLANMAN
+                       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");
                        return NOT_AUTHENTICATED;
-#endif /* MSLANMAN */
+#endif /* PPP_WITH_MSLANMAN */
                }
                
                /* ship off to winbind, and check */
@@ -584,15 +579,14 @@ 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);
+#ifdef PPP_WITH_MPPE
+                       mppe_set_chapv1(challenge, session_key);
+#endif
                        slprintf(message, message_space, "Access granted");
                        return AUTHENTICATED;
                        
@@ -610,15 +604,15 @@ 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];
+               u_char session_key[MD4_DIGEST_LENGTH];
                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 */
                
@@ -626,22 +620,22 @@ 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);
+#ifdef PPP_WITH_MPPE
+                       mppe_set_chapv2(session_key, &response[MS_CHAP2_NTRESP],
+                                      MS_CHAP2_AUTHENTICATOR);
+#endif
+                       if (response[MS_CHAP2_FLAGS]) {
                                slprintf(message, message_space, "S=%s", saresponse);
                        } else {
                                slprintf(message, message_space, "S=%s M=%s",
@@ -671,7 +665,7 @@ winbind_chap_verify(char *user, char *ourname, int id,
 }
 
 static int 
-winbind_allowed_address(u_int32_t addr) 
+winbind_allowed_address(uint32_t addr)
 {
        ipcp_options *wo = &ipcp_wantoptions[0];
        if (wo->hisaddr !=0 && wo->hisaddr == addr) {