Esempio n. 1
0
bool TMsg::validateAuthInfo(char *buf, int bufSize,
                            AuthProtocols proto,
                            const DigestTypesLst& acceptedDigestTypes) {
    bool is_ok = false;
    bool dt_in_list = false;

    switch (proto) {
    case AUTH_PROTO_NOT_SUPPORTED:
    case AUTH_PROTO_NONE:
        return true;
    case AUTH_PROTO_DELAYED: {
        SPtr<TOptAuthentication> auth = (Ptr*)getOption(OPTION_AUTH);
        if (!auth) {
            Log(Warning) << "AUTH: Mandatory AUTH option missing in delayed auth."
                         << LogEnd;
            return false;
        }
        if (auth->getProto() != AUTH_PROTO_DELAYED) {
            Log(Warning) << "AUTH: Bad protocol in auth: expected 2(delayed auth), but got "
                         << int(auth->getProto()) << ", key ignored." << LogEnd;
            return false;
        }
        if (auth->getAlgorithm() != 1) {
            Log(Warning) << "AUTH: Bad algorithm in auth option: expected 1 (HMAC-MD5), but got "
                         << int(auth->getAlgorithm()) << ", key ignored." << LogEnd;
            return false;
        }
        if (MsgType == SOLICIT_MSG) {
            if (auth->getSize() != TOptAuthentication::OPT_AUTH_FIXED_SIZE + TOpt::OPTION6_HDR_LEN) {
                Log(Warning) << "AUTH: Received non-empty delayed-auth option in SOLICIT,"
                             << " expected empty." << LogEnd;
                return false;
            } else {
                return true; // delayed auth in Solicit should come in empty
            }
        }

        if (SPI_ == 0) {
            Log(Warning) << "AUTH: Received invalid SPI = 0." << LogEnd;
            return false;
        }

        if (!loadAuthKey()) {
            Log(Warning) << "AUTH: Failed to load delayed auth key with key id="
                         << std::hex << getSPI() << std::dec << LogEnd;
            return false;
        }

        // Ok, let's do validation
        char *rcvdAuthInfo = new char[RECONFIGURE_DIGEST_SIZE];
        char *goodAuthInfo = new char[RECONFIGURE_DIGEST_SIZE];

        memmove(rcvdAuthInfo, AuthDigestPtr_, DELAYED_AUTH_DIGEST_SIZE);
        memset(AuthDigestPtr_, 0, DELAYED_AUTH_DIGEST_SIZE);

        hmac_md5(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo);

        Log(Debug) << "Auth: Checking delayed-auth (HMAC-MD5) digest:" << LogEnd;
        PrintHex("Auth:received digest: ", (uint8_t*)rcvdAuthInfo, DELAYED_AUTH_DIGEST_SIZE);
        PrintHex("Auth:  proper digest: ", (uint8_t*)goodAuthInfo, DELAYED_AUTH_DIGEST_SIZE);

        if (0 == memcmp(goodAuthInfo, rcvdAuthInfo, DELAYED_AUTH_DIGEST_SIZE))
            is_ok = true;

        delete [] rcvdAuthInfo;
        delete [] goodAuthInfo;

        return is_ok;
    }
    case AUTH_PROTO_RECONFIGURE_KEY: {
        if (MsgType != RECONFIGURE_MSG)
            return true;
        SPtr<TOptAuthentication> auth = (Ptr*)getOption(OPTION_AUTH);
        if (!auth) {
            Log(Warning) << "AUTH: Mandatory AUTH option missing in RECONFIGURE." << LogEnd;
            return false;
        }
        if (auth->getProto() != AUTH_PROTO_RECONFIGURE_KEY) {
            Log(Warning) << "AUTH: Bad protocol in auth: expected 3(reconfigure-key), but got "
                         << int(auth->getProto()) << ", key ignored." << LogEnd;
            return false;
        }
        if (auth->getAlgorithm() != 1) {
            Log(Warning) << "AUTH: Bad algorithm in auth option: expected 1, but got "
                         << int(auth->getAlgorithm()) << ", key ignored." << LogEnd;
            return false;
        }
        if (auth->getRDM() != AUTH_REPLAY_NONE) {
            Log(Warning) << "AUTH: Bad replay detection method (RDM) value: expected 0,"
                         << ", but got " << auth->getRDM() << LogEnd;
            // This is small issue enough, so we can continue.
        }
        if (AuthKey_.size() != RECONFIGURE_KEY_SIZE) {
            Log(Error) << "AUTH: Failed to verify incoming RECONFIGURE message due to "
                       << "reconfigure-key issue: expected size " << RECONFIGURE_KEY_SIZE
                       << ", but got " << AuthKey_.size() << ", message dropped." << LogEnd;
            return false;
        }
        if (!AuthDigestPtr_) {
            Log(Error) << "AUTH: Failed to verify incoming RECONFIGURE message: "
                       << "AuthDigestPtr_ not set, message dropped." << LogEnd;
            return false;
        }

        char *rcvdAuthInfo = new char[RECONFIGURE_DIGEST_SIZE];
        char *goodAuthInfo = new char[RECONFIGURE_DIGEST_SIZE];

        memmove(rcvdAuthInfo, AuthDigestPtr_, RECONFIGURE_DIGEST_SIZE);
        memset(AuthDigestPtr_, 0, RECONFIGURE_DIGEST_SIZE);

        hmac_md5(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo);

        Log(Debug) << "Auth: Checking reconfigure-key" << LogEnd;
        PrintHex("Auth:received digest: ", (uint8_t*)rcvdAuthInfo, RECONFIGURE_DIGEST_SIZE);
        PrintHex("Auth:  proper digest: ", (uint8_t*)goodAuthInfo, RECONFIGURE_DIGEST_SIZE);

        if (0 == memcmp(goodAuthInfo, rcvdAuthInfo, RECONFIGURE_DIGEST_SIZE))
            is_ok = true;

        delete [] rcvdAuthInfo;
        delete [] goodAuthInfo;

        return is_ok;
    }
    case AUTH_PROTO_DIBBLER:
        break;
    }
    
    //empty list means that any digest type is accepted
    if (acceptedDigestTypes.empty()) {
        dt_in_list = true;
    } else {
        // check if the digest is allowed AUTH list
        for (unsigned i = 0; i < acceptedDigestTypes.size(); ++i) {
            if (acceptedDigestTypes[i] == DigestType_) {
                dt_in_list = true;
                break;
            }
        }
    }

    if (dt_in_list == false) {
        if (DigestType_ == DIGEST_NONE)
            Log(Warning) << "Authentication option is required." << LogEnd;
        else
            Log(Warning) << "Authentication method " << getDigestName(DigestType_)
                       << " not accepted." << LogEnd;
        return false;
    }

    if (DigestType_ == DIGEST_NONE) {
            is_ok = true;
    } else if (AuthDigestPtr_) {
#ifndef MOD_DISABLE_AUTH

        if (AuthKey_.empty() && !loadAuthKey()) {
            Log(Debug) << "Auth: Failed to load key with SPI=" << SPI_ << LogEnd;
            return false;
        }

        unsigned AuthInfoLen = getDigestSize(DigestType_);
        char *rcvdAuthInfo = new char[AuthInfoLen];
        char *goodAuthInfo = new char[AuthInfoLen];

        memmove(rcvdAuthInfo, AuthDigestPtr_, AuthInfoLen);
        memset(AuthDigestPtr_, 0, AuthInfoLen);

        switch (DigestType_) {
                case DIGEST_PLAIN:
                    /// @todo: load plain text from a file
                    memcpy(goodAuthInfo, "This is 32-byte plain testkey...", 32);
                    break;
                case DIGEST_HMAC_MD5:
                    hmac_md5(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo);
                    break;
                case DIGEST_HMAC_SHA1:
                    hmac_sha(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo, 1);
                    break;
                case DIGEST_HMAC_SHA224:
                    hmac_sha(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo, 224);
                    break;
                case DIGEST_HMAC_SHA256:
                    hmac_sha(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo, 256);
                    break;
                case DIGEST_HMAC_SHA384:
                    hmac_sha(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo, 384);
                    break;
                case DIGEST_HMAC_SHA512:
                    hmac_sha(buf, bufSize, (char*)&AuthKey_[0], AuthKey_.size(), goodAuthInfo, 512);
                    break;
                default:
                    break;
        }
        if (0 == memcmp(goodAuthInfo, rcvdAuthInfo, AuthInfoLen))
            is_ok = true;

        Log(Debug) << "Auth:Checking using digest method: "
                   << getDigestName(DigestType_) << LogEnd;
        PrintHex("Auth:received digest: ", (uint8_t*)rcvdAuthInfo, AuthInfoLen);
        PrintHex("Auth:  proper digest: ", (uint8_t*)goodAuthInfo, AuthInfoLen);

        delete [] rcvdAuthInfo;
        delete [] goodAuthInfo;

        if (is_ok)
            Log(Info) << "Auth: Digest correct." << LogEnd;
        else {
            Log(Warning) << "Auth: Digest incorrect." << LogEnd;
	}
#endif
    } else {
        Log(Error) << "Auth: Digest mode set to " << DigestType_
                   << ", but AUTH option not set." << LogEnd;
        return false;
    }
    
    return is_ok;
}
Esempio n. 2
0
/* prepares binary version of this message, returns number of bytes used
**/
int TMsg::storeSelf(char * buffer)
{
    char *start = buffer;
    int tmp = this->TransID;

    enum DigestTypes UsedDigestType;
    
    if (Bulk) {

        int tmpSize = this->MsgSize;
        Log(Debug) <<"MsgSize - DHCP "<<this->MsgSize<< LogEnd;
        buffer[1]=tmpSize%256; tmpSize/=256;
        buffer[0]=tmpSize%256; tmpSize/=256;

        buffer[2]=(char)MsgType;
        buffer[5] = tmp%256;  tmp = tmp/256;
        buffer[4] = tmp%256;  tmp = tmp/256;
        buffer[3] = tmp%256;  tmp = tmp/256;
        buffer+=6;

    } else {

        *(buffer++) = (char)MsgType;

        /* ugly 3-byte version of htons/htonl */
        buffer[2] = tmp%256;  tmp = tmp/256;
        buffer[1] = tmp%256;  tmp = tmp/256;
        buffer[0] = tmp%256;  tmp = tmp/256;
        buffer+=3;
    }

    TOptList::iterator option;
    for (option=Options.begin(); option!=Options.end(); ++option) {
        (*option)->storeSelf(buffer);
	buffer += (*option)->getSize();
    }

#ifndef MOD_DISABLE_AUTH
    // for AAAAUTH use only HMAC-SHA1
    if (getOption(OPTION_AAAAUTH))
            UsedDigestType = DIGEST_HMAC_SHA1;
    else
            UsedDigestType = DigestType;

    if (AuthInfoKey && AuthInfoPtr && (getOption(OPTION_AUTH) || getOption(OPTION_AAAAUTH)) && UsedDigestType != DIGEST_NONE) {
            Log(Debug) << "Auth: Used digest type is " << getDigestName(UsedDigestType) << LogEnd;
            switch (UsedDigestType) {
                    case DIGEST_PLAIN:
                        memcpy(AuthInfoPtr, "This is 32-byte plain testkey...", getDigestSize(UsedDigestType));
                        break;
                    case DIGEST_HMAC_MD5:
                        hmac_md5(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr);
                        break;
                    case DIGEST_HMAC_SHA1:
                        hmac_sha(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr, 1);
                        break;
                    case DIGEST_HMAC_SHA224:
                        hmac_sha(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr, 224);
                        break;
                    case DIGEST_HMAC_SHA256:
                        hmac_sha(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr, 256);
                        break;
                    case DIGEST_HMAC_SHA384:
                        hmac_sha(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr, 384);
                        break;
                    case DIGEST_HMAC_SHA512:
                        hmac_sha(start, buffer-start, AuthInfoKey, AUTHKEYLEN, (char *)AuthInfoPtr, 512);
                        break;
                    default:
                        break;
            }
            PrintHex("Auth: Sending digest: ", AuthInfoPtr, getDigestSize(UsedDigestType));
    }
#endif

    return buffer-start;
}
Esempio n. 3
0
void TMsg::calculateDigests(char* buffer, size_t len) {

    SPtr<TOptAuthentication> auth = (Ptr*)getOption(OPTION_AUTH);
    if (!auth)
        return;

    switch (auth->getProto()) {
    default: {
        Log(Error) << "AUTH: protocol " << auth->getProto() << " not supported yet." << LogEnd;
        return;
    }
    case AUTH_PROTO_DELAYED: {
        if (AuthKey_.empty()) {
            if (MsgType == SOLICIT_MSG) {
                return; // That's alright, no auth info in SOLICIT
            }
            Log(Error) << "AUTH: Can't sign delayed-auth option, key empty." << LogEnd;
            return;
        }
        if (auth->getAuthDataPtr()) {
            hmac_md5(buffer, len, (char*) &AuthKey_[0], AuthKey_.size() ,auth->getAuthDataPtr());
        }
        return;
    }
    case AUTH_PROTO_RECONFIGURE_KEY: {
        if (AuthKey_.size() != RECONFIGURE_KEY_SIZE) {
            Log(Error) << "AUTH: Invalid size of reconfigure-key: expected " <<
                RECONFIGURE_KEY_SIZE << ", actual size " << AuthKey_.size() << LogEnd;
            return;
        }
        if (auth->getAuthDataPtr()) {
            hmac_md5(buffer, len, (char*) &AuthKey_[0], AuthKey_.size() ,auth->getAuthDataPtr());
        }
        return;
    }
    case AUTH_PROTO_NOT_SUPPORTED:
    case AUTH_PROTO_NONE: {
        // don't calculate anything
        return;
    }
    case AUTH_PROTO_DIBBLER: {
        DigestTypes UsedDigestType;

	// for AAAAUTH use only HMAC-SHA1
        UsedDigestType = DigestType_;

        if (getSPI() && !loadAuthKey()) {
            return;
        }
        
        if (getSPI() && !AuthKey_.empty() && UsedDigestType != DIGEST_NONE) {
            Log(Debug) << "Auth: Used digest type is " << getDigestName(UsedDigestType) << LogEnd;
            switch (UsedDigestType) {
            case DIGEST_PLAIN:
                memcpy(AuthDigestPtr_, "This is 32-byte plain testkey...", getDigestSize(UsedDigestType));
                break;
            case DIGEST_HMAC_MD5:
                hmac_md5(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_);
                break;
            case DIGEST_HMAC_SHA1:
                hmac_sha(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_, 1);
                break;
            case DIGEST_HMAC_SHA224:
                hmac_sha(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_, 224);
                break;
            case DIGEST_HMAC_SHA256:
                hmac_sha(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_, 256);
                break;
            case DIGEST_HMAC_SHA384:
                hmac_sha(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_, 384);
                break;
            case DIGEST_HMAC_SHA512:
                hmac_sha(buffer, len, (char*)&AuthKey_[0], AuthKey_.size(), (char *)AuthDigestPtr_, 512);
                break;
            default:
                break;
            }
            PrintHex(std::string("Auth: Sending digest ") + getDigestName(UsedDigestType) +" : ",
				 (uint8_t*)AuthDigestPtr_, getDigestSize(UsedDigestType));
        }
    }
    }

}