summaryrefslogtreecommitdiff
path: root/src/mongo/db/security.h
blob: e5c5cd07ea758ada114f9b86102dc42ed1bb1d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// security.h

/**
*    Copyright (C) 2009 10gen Inc.
*
*    This program is free software: you can redistribute it and/or  modify
*    it under the terms of the GNU Affero General Public License, version 3,
*    as published by the Free Software Foundation.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <string>

#include "mongo/db/security_common.h"
#include "mongo/client/authentication_table.h"
#include "mongo/client/authlevel.h"
#include "mongo/util/concurrency/spin_lock.h"

// this is used by both mongos and mongod

namespace mongo {

    /** An AuthenticationInfo object is present within every mongo::Client object */
    class AuthenticationInfo : boost::noncopyable {
        bool _isLocalHost;
        bool _isLocalHostAndLocalHostIsAuthorizedForAll;
    public:
        void startRequest(); // need to call at the beginning of each request
        void setIsALocalHostConnectionWithSpecialAuthPowers(); // called, if localhost, when conneciton established.
        AuthenticationInfo() {
            _isLocalHost = false; 
            _isLocalHostAndLocalHostIsAuthorizedForAll = false;
            _usingTempAuth = false;
        }
        ~AuthenticationInfo() {}
        bool isLocalHost() const { return _isLocalHost; } // why are you calling this? makes no sense to be externalized
        bool isSpecialLocalhostAdmin() const;

        // -- modifiers ----
        
        void logout(const std::string& dbname ) {
            scoped_spinlock lk(_lock);
            _authTable.removeAuth( dbname );
        }
        void authorize(const std::string& dbname , const std::string& user ) {
            scoped_spinlock lk(_lock);
            _authTable.addAuth( dbname, user, Auth::WRITE );
        }
        void authorizeReadOnly(const std::string& dbname , const std::string& user ) {
            scoped_spinlock lk(_lock);
            _authTable.addAuth( dbname, user, Auth::READ );
        }
        
        // -- accessors ---

        bool isAuthorized(const std::string& dbname) const { 
            return _isAuthorized( dbname, Auth::WRITE ); 
        }
        
        bool isAuthorizedReads(const std::string& dbname) const { 
            return _isAuthorized( dbname, Auth::READ ); 
        }
        
        /**
         * @param lockType - this is from dbmutex 1 is write, 0 is read
         */
        bool isAuthorizedForLock(const std::string& dbname, int lockType ) const { 
            return _isAuthorized( dbname , lockType > 0 ? Auth::WRITE : Auth::READ ); 
        }

        std::string getUser( const std::string& dbname ) const;

        void print() const;

        BSONObj toBSON() const;

        void setTemporaryAuthorization( BSONObj& obj );
        void clearTemporaryAuthorization();
        bool hasTemporaryAuthorization();

        // Returns true if this AuthenticationInfo has been auth'd to use the internal user
        bool usingInternalUser();

        // When TemporaryAuthReleaser goes out of scope it clears the temporary authentication set
        // in its AuthenticationInfo object, unless that AuthenticationInfo already had temporary
        // auth set at the time that the TemporaryAuthReleaser was initialized.
        class TemporaryAuthReleaser : boost::noncopyable {
        public:
            TemporaryAuthReleaser ( AuthenticationInfo* ai );
            ~TemporaryAuthReleaser();
        private:
            AuthenticationInfo* _ai;
            bool _hadTempAuthFromStart;
        };

    private:
        void _checkLocalHostSpecialAdmin();

        /** takes a lock */
        bool _isAuthorized(const std::string& dbname, Auth::Level level) const;

        // Must be in _lock
        bool _isAuthorizedSingle_inlock(const std::string& dbname, Auth::Level level) const;
        
        /** cannot call this locked */
        bool _isAuthorizedSpecialChecks( const std::string& dbname ) const ;

        // Must be in _lock
        void _addTempAuth_inlock( const std::string& dbname, const std::string& user,
                                  Auth::Level level);

    private:
        // while most access to _authTable is from our thread (the TLS thread), currentOp()
        // inspects it too thus we need this.
        // This protects _authTable, _tempAuthTable, and _usingTempAuth.
        mutable SpinLock _lock;

        // todo: caching should not last forever
        AuthenticationTable _authTable;
        // when _usingTempAuth is true, this is used for all auth checks instead of _authTable
        AuthenticationTable _tempAuthTable;

        bool _usingTempAuth;
        static bool _warned;
    };

} // namespace mongo