Changeset 7bf255b in github


Ignore:
Timestamp:
Oct 22, 2010 2:52:20 PM (3 years ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
Children:
63d4d611
Parents:
cb7d32e
Message:
  • Add SASL-IR support (RFC 4959)
  • Add LOGINDISABLED support (RFC 2595)
  • Add support for AUTH=PLAIN authentication to IMAP
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    rcb7d32e r7bf255b  
    2222- Add unique index on users.username+users.mail_host 
    2323- Make htmleditor option more consistent and add option to use HTML on reply to HTML message (#1485840) 
    24 - Use empty envelope sender address for message disposition notifications (RFC2298.3) 
    25 - Support SMTP Delivery Status Notifications - RFC3461 (#1486142) 
     24- Use empty envelope sender address for message disposition notifications (RFC 2298.3) 
     25- Support SMTP Delivery Status Notifications - RFC 3461 (#1486142) 
    2626- Use css sprite image for messages list 
    2727- Add (different) attachment icon for messages of type multipart/report (#1486165) 
     
    3232- Fix double e-mail filed in identity form (#1487054) 
    3333- Display IMAP errors for LIST/THREAD/SEARCH commands (#1486905) 
    34 - Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC2088) 
     34- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC 2088) 
    3535- Add separate column for message status icon (#1486665) 
    36 - Add ACL extension support into IMAP classes (RFC4314) 
     36- Add ACL extension support into IMAP classes (RFC 4314) 
    3737- Add ANNOTATEMORE extension support into IMAP classes (draft-daboo-imap-annotatemore) 
    38 - Add METADATA extension support into IMAP classes (RFC5464) 
     38- Add METADATA extension support into IMAP classes (RFC 5464) 
    3939- Fix decoding of e-mail address strings in message headers (#1487068) 
    4040- Fix handling of attachments when Content-Disposition is not inline nor attachment (#1487051) 
    4141- Improve performance of unseen messages counting (#1487058) 
    4242- Improve performance of messages counting using ESEARCH extension (RFC4731) 
    43 - Add LIST-STATUS support in rcube_imap_generic class (RFC5819) 
     43- Add LIST-STATUS support in rcube_imap_generic class (RFC 5819) 
     44- Add SASL-IR support in IMAP (RFC 4959) 
     45- Add LOGINDISABLED support (RFC 2595) 
     46- Add support for AUTH=PLAIN in IMAP authentication 
    4447 
    4548RELEASE 0.4.2 
  • config/main.inc.php.dist

    r4438d667 r7bf255b  
    7171$rcmail_config['default_port'] = 143; 
    7272 
    73 // IMAP auth type. Can be "auth" (CRAM-MD5), "plain" (PLAIN) or "check" to auto detect. 
    74 // Optional, defaults to "check" 
     73// IMAP auth type. Can be "auth" (CRAM-MD5), "plain" (PLAIN), "login" (LOGIN) 
     74// or "check" (or empty) to auto detect. Optional, defaults to "check" 
    7575$rcmail_config['imap_auth_type'] = null; 
    7676 
  • program/include/rcube_imap_generic.php

    r6a16031 r7bf255b  
    371371    } 
    372372 
    373     function authenticate($user, $pass, $encChallenge) 
    374     { 
    375         $ipad = ''; 
    376         $opad = ''; 
    377  
    378         // initialize ipad, opad 
    379         for ($i=0; $i<64; $i++) { 
    380             $ipad .= chr(0x36); 
    381             $opad .= chr(0x5C); 
    382         } 
    383  
    384         // pad $pass so it's 64 bytes 
    385         $padLen = 64 - strlen($pass); 
    386         for ($i=0; $i<$padLen; $i++) { 
    387             $pass .= chr(0); 
    388         } 
    389  
    390         // generate hash 
    391         $hash  = md5($this->_xor($pass,$opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge)))); 
    392  
    393         // generate reply 
    394         $reply = base64_encode($user . ' ' . $hash); 
    395  
    396         // send result, get reply 
    397         $this->putLine($reply); 
    398         $line = $this->readLine(1024); 
    399  
    400         // process result 
    401         $result = $this->parseResult($line); 
     373    /** 
     374     * CRAM-MD5/PLAIN Authentication 
     375     * 
     376     * @param string $user 
     377     * @param string $pass 
     378     * @param string $type Authentication type (PLAIN or CRAM-MD5) 
     379     * 
     380     * @return resource Connection resourse on success, error code on error 
     381     */ 
     382    function authenticate($user, $pass, $type='PLAIN') 
     383    { 
     384        if ($type == 'CRAM-MD5') { 
     385            $ipad = ''; 
     386            $opad = ''; 
     387 
     388            // initialize ipad, opad 
     389            for ($i=0; $i<64; $i++) { 
     390                $ipad .= chr(0x36); 
     391                $opad .= chr(0x5C); 
     392            } 
     393 
     394            // pad $pass so it's 64 bytes 
     395            $padLen = 64 - strlen($pass); 
     396            for ($i=0; $i<$padLen; $i++) { 
     397                $pass .= chr(0); 
     398            } 
     399 
     400                    $this->putLine($this->next_tag() . " AUTHENTICATE CRAM-MD5"); 
     401                    $line = trim($this->readLine(1024)); 
     402 
     403                    if ($line[0] == '+') { 
     404                            $challenge = substr($line,2); 
     405            } 
     406            else { 
     407                            return self::ERROR_BYE; 
     408                    } 
     409 
     410            // generate hash 
     411            $hash  = md5($this->_xor($pass, $opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge)))); 
     412            $reply = base64_encode($user . ' ' . $hash); 
     413 
     414            // send result, get reply and process it 
     415            $this->putLine($reply); 
     416            $line = $this->readLine(1024); 
     417            $result = $this->parseResult($line); 
     418            if ($result != self::ERROR_OK) { 
     419                $this->set_error($result, "Unble to authenticate user (CRAM-MD5): $line"); 
     420            } 
     421        } 
     422        else { // PLAIN 
     423            $reply = base64_encode($user . chr(0) . $user . chr(0) . $pass); 
     424 
     425            // RFC 4959 (SASL-IR): save one round trip 
     426            if ($this->getCapability('SASL-IR')) { 
     427                $result = $this->execute("AUTHENTICATE PLAIN", array($reply), self::COMMAND_NORESPONSE); 
     428            } 
     429            else { 
     430                    $this->putLine($this->next_tag() . " AUTHENTICATE PLAIN"); 
     431                    $line = trim($this->readLine(1024)); 
     432 
     433                        if ($line[0] != '+') { 
     434                            return self::ERROR_BYE; 
     435                    } 
     436 
     437                // send result, get reply and process it 
     438                $this->putLine($reply); 
     439                $line = $this->readLine(1024); 
     440                $result = $this->parseResult($line); 
     441                if ($result != self::ERROR_OK) { 
     442                    $this->set_error($result, "Unble to authenticate user (AUTH): $line"); 
     443                } 
     444            } 
     445        } 
     446 
    402447        if ($result == self::ERROR_OK) { 
    403448            return $this->fp; 
    404449        } 
    405450 
    406         $this->error = "Authentication for $user failed (AUTH): $line"; 
    407  
    408451        return $result; 
    409452    } 
    410453 
     454    /** 
     455     * LOGIN Authentication 
     456     * 
     457     * @param string $user 
     458     * @param string $pass 
     459     * 
     460     * @return resource Connection resourse on success, error code on error 
     461     */ 
    411462    function login($user, $password) 
    412463    { 
     
    422473            return $this->fp; 
    423474        } 
    424  
    425         @fclose($this->fp); 
    426         $this->fp    = false; 
    427475 
    428476        return $code; 
     
    635683            } 
    636684 
    637             $orig_method = $auth_method; 
    638  
     685            $auth_methods = array(); 
     686        $result       = null; 
     687 
     688            // check for supported auth methods 
    639689            if ($auth_method == 'CHECK') { 
    640                     // check for supported auth methods 
    641690                    if ($this->getCapability('AUTH=CRAM-MD5') || $this->getCapability('AUTH=CRAM_MD5')) { 
    642                             $auth_method = 'AUTH'; 
     691                            $auth_methods[] = 'AUTH'; 
    643692                    } 
    644                     else { 
    645                             // default to plain text auth 
    646                             $auth_method = 'PLAIN'; 
     693                    if ($this->getCapability('AUTH=PLAIN')) { 
     694                            $auth_methods[] = 'PLAIN'; 
    647695                    } 
    648             } 
    649  
    650             if ($auth_method == 'AUTH') { 
    651                     // do CRAM-MD5 authentication 
    652                     $this->putLine($this->next_tag() . " AUTHENTICATE CRAM-MD5"); 
    653                     $line = trim($this->readLine(1024)); 
    654  
    655                     if ($line[0] == '+') { 
    656                             // got a challenge string, try CRAM-MD5 
    657                             $result = $this->authenticate($user, $password, substr($line,2)); 
    658  
    659                             // stop if server sent BYE response 
    660                             if ($result == self::ERROR_BYE) { 
    661                                     return false; 
    662                             } 
     696            // RFC 2595 (LOGINDISABLED) LOGIN disabled when connection is not secure 
     697                    if (!$this->getCapability('LOGINDISABLED')) { 
     698                            $auth_methods[] = 'LOGIN'; 
    663699                    } 
    664  
    665                     if (!is_resource($result) && $orig_method == 'CHECK') { 
    666                             $auth_method = 'PLAIN'; 
     700            } 
     701        else { 
     702            $auth_methods[] = $auth_method; 
     703        } 
     704 
     705        // Authenticate 
     706        foreach ($auth_methods as $method) { 
     707            switch ($method) { 
     708            case 'AUTH': 
     709                            $result = $this->authenticate($user, $password, 'CRAM-MD5'); 
     710                        break; 
     711                case 'PLAIN': 
     712                            $result = $this->authenticate($user, $password, 'PLAIN'); 
     713                        break; 
     714            case 'LOGIN': 
     715                $result = $this->login($user, $password); 
     716                break; 
     717            default: 
     718                $this->set_error(self::ERROR_BAD, "Configuration error. Unknown auth method: $method"); 
     719            } 
     720 
     721                    if (is_resource($result)) { 
     722                            break; 
    667723                    } 
    668724            } 
    669725 
    670             if ($auth_method == 'PLAIN') { 
    671                     // do plain text auth 
    672                     $result = $this->login($user, $password); 
    673             } 
    674  
     726        // Connected and authenticated 
    675727            if (is_resource($result)) { 
    676728            if ($this->prefs['force_caps']) { 
     
    681733 
    682734                    return true; 
    683             } else { 
    684                     return false; 
    685             } 
     735        } 
     736 
     737        // Close connection 
     738        @fclose($this->fp); 
     739        $this->fp = false; 
     740 
     741            return false; 
    686742    } 
    687743 
Note: See TracChangeset for help on using the changeset viewer.