예제 #1
0
    def PUT(self):
        """
        This function permit to add or update a ssh public key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.
        """
        # LDAP authentication
        is_auth, message = tools.ldap_authentification(SERVER_OPTS)
        if not is_auth:
            return tools.response_render(message, http_code='401 Unauthorized')

        payload, message = tools.data2map()
        if message:
            return tools.response_render(message, http_code='400 Bad Request')

        if 'username' in payload:
            username = payload['username']
        else:
            return tools.response_render(
                'Error: No username option given.',
                http_code='400 Bad Request')

        if username == 'all':
            return tools.response_render(
                "Error: username not valid.",
                http_code='400 Bad Request')


        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return tools.response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        if constants.PATTERN_REALNAME.match(realname) is None:
            return tools.response_render(
                "Error: realname doesn't match pattern",
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = tools.unquote_custom(payload['pubkey'])
        else:
            return tools.response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        if pg_conn is None:
            remove(tmp_pubkey.name)
            return tools.response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute(
            """
            SELECT 1 FROM USERS WHERE NAME=(%s)
            """, (username,))
        user = cur.fetchone()
        # CREATE NEW USER
        if user is None:
            cur.execute(
                """
                INSERT INTO USERS VALUES ((%s), (%s), (%s), (%s), (%s), (%s), (%s), (%s))
                """, (
                    username, realname, constants.STATES['PENDING'],
                    0, pubkey_fingerprint, pubkey, '+12h', username))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Create user=%s. Pending request.' % username,
                http_code='201 Created')
        # Check if realname is the same
        cur.execute(
            """
            SELECT 1 FROM USERS WHERE NAME=(%s) AND REALNAME=lower((%s))
            """, (username, realname))
        if cur.fetchone() is None:
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : (username, realname) couple mismatch.',
                http_code='401 Unauthorized')
        # Update entry into database
        cur.execute(
            """
            UPDATE USERS
            SET SSH_KEY=(%s),SSH_KEY_HASH=(%s), STATE=(%s), EXPIRATION=0
            WHERE NAME=(%s)
            """, (pubkey, pubkey_fingerprint, constants.STATES['PENDING'], username))
        pg_conn.commit()
        cur.close()
        pg_conn.close()
        remove(tmp_pubkey.name)
        return tools.response_render('Update user=%s. Pending request.' % username)
예제 #2
0
    def PUT(self):
        """
        This function permit to add or update a ssh public key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return message

        payload = data2map()

        if payload.has_key('username'):
            username = payload['username']
        else:
            return "Error: No username option given."

        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return "Error: Username %s doesn't match pattern %s" \
                % (username, username_pattern.pattern)

        if payload.has_key('realname'):
            realname = unquote_plus(payload['realname'])
        else:
            return "Error: No realname option given."

        # Get public key
        if payload.has_key('pubkey'):
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return "Error: No pubkey given."
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(pubkey)
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return 'Error : Public key unprocessable'

        pg_conn, message = pg_connection()
        if pg_conn is None:
            remove(tmp_pubkey.name)
            return message
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute('SELECT * FROM USERS WHERE NAME=(%s)', (username, ))
        user = cur.fetchone()

        # CREATE NEW USER
        if user is None:
            cur.execute('INSERT INTO USERS VALUES \
                ((%s), (%s), (%s), (%s), (%s), (%s), (%s), (%s))'                                                                 , \
                (username, realname, 2, 0, pubkey_fingerprint, pubkey, '+12h', ''))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return 'Create user=%s. Pending request.' % username
        else:
            # Check if realname is the same
            cur.execute('SELECT * FROM USERS WHERE NAME=(%s) AND REALNAME=lower((%s))', \
                (username, realname))
            if cur.fetchone() is None:
                pg_conn.commit()
                cur.close()
                pg_conn.close()
                remove(tmp_pubkey.name)
                return 'Error : (username, realname) couple mismatch.'
            # Update entry into database
            cur.execute(
                'UPDATE USERS SET SSH_KEY=(%s), SSH_KEY_HASH=(%s), STATE=2, EXPIRATION=0 \
                WHERE NAME=(%s)', (pubkey, pubkey_fingerprint, username))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return 'Update user=%s. Pending request.' % username
예제 #3
0
    def POST(self):
        """
        Ask to sign pub key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.

            # Optionnal
            admin_force=true|false
        """
        # LDAP authentication
        is_auth, message = tools.ldap_authentification(SERVER_OPTS)
        if not is_auth:
            return tools.response_render(message, http_code='401 Unauthorized')

        # Check if user is an admin and want to force signature when db fail
        force_sign = False

        # LDAP ADMIN authentication
        is_admin_auth, message = tools.ldap_authentification(
            SERVER_OPTS, admin=True)

        payload, message = tools.data2map()
        if message:
            return tools.response_render(message, http_code='400 Bad Request')

        if is_admin_auth and SERVER_OPTS['admin_db_failover'] \
            and 'admin_force' in payload and payload['admin_force'].lower() == 'true':
            force_sign = True

        # Get username
        if 'username' in payload:
            username = payload['username']
        else:
            return tools.response_render(
                'Error: No username option given.',
                http_code='400 Bad Request')
        if username == 'all':
            return tools.response_render(
                "Error: username not valid.",
                http_code='400 Bad Request')

        # Get realname
        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return tools.response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = tools.unquote_custom(payload['pubkey'])
        else:
            return tools.response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        # Admin force signature case
        if pg_conn is None and force_sign:
            cert_contents = TOOLS.sign_key(tmp_pubkey.name, username, '+12h', username)
            remove(tmp_pubkey.name)
            return tools.response_render(cert_contents, content_type='application/octet-stream')
        # Check if db is up
        if pg_conn is None:
            remove(tmp_pubkey.name)
            return tools.response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if user already exists
        cur.execute(
            """
            SELECT NAME,REALNAME,STATE,EXPIRY,PRINCIPALS,SSH_KEY FROM USERS
            WHERE NAME=lower(%s)
            """, (username,))
        user = cur.fetchone()
        if user is None:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : User absent, please create an account.',
                http_code='400 Bad Request')

        # Get database key fingerprint
        db_pubkey = NamedTemporaryFile(delete=False)
        db_pubkey.write(bytes(user[5], 'utf-8'))
        db_pubkey.close()
        db_pubkey_fingerprint = get_fingerprint(db_pubkey.name)
        remove(db_pubkey.name)

        if db_pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : Public key from database unprocessable',
                http_code='422 Unprocessable Entity')

        if username != user[0] or \
            realname != user[1] or \
            db_pubkey_fingerprint != pubkey_fingerprint:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return tools.response_render(
                'Error : (username, realname, pubkey) triple mismatch.',
                http_code='401 Unauthorized')

        status = user[2]
        expiry = user[3]
        custom_principals = tools.clean_principals_output(user[4], username, shell=True)
        list_membership, _ = tools.get_memberof(
            realname,
            SERVER_OPTS)
        full_principals = tools.merge_principals(custom_principals, list_membership, SERVER_OPTS)

        if status > 0:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return tools.response_render("Status: %s" % constants.STATES[user[2]])

        cert_contents = TOOLS.sign_key(
            tmp_pubkey.name, username, expiry, full_principals, db_cursor=cur)

        remove(tmp_pubkey.name)
        pg_conn.commit()
        cur.close()
        pg_conn.close()
        return tools.response_render(
            cert_contents,
            content_type='application/octet-stream')
예제 #4
0
    def POST(self):
        """
        Ask to sign pub key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.

            # Optionnal
            admin_force=true|false
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return message

        # Check if user is an admin and want to force signature when db fail
        force_sign = False

        # LDAP ADMIN authentication
        is_admin_auth, _ = ldap_authentification(admin=True)

        payload = data2map()

        if is_admin_auth and SERVER_OPTS['admin_db_failover'] \
            and payload.has_key('admin_force') and payload['admin_force'].lower() == 'true':
            force_sign = True

        # Get username
        if payload.has_key('username'):
            username = payload['username']
        else:
            return "Error: No username option given. Update your CASSH >= 1.3.0"
        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return "Error: Username %s doesn't match pattern %s" \
                % (username, username_pattern.pattern)

        # Get realname
        if payload.has_key('realname'):
            realname = unquote_plus(payload['realname'])
        else:
            return "Error: No realname option given."

        # Get public key
        if payload.has_key('pubkey'):
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return "Error: No pubkey given."
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(pubkey)
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return 'Error : Public key unprocessable'

        pg_conn, message = pg_connection()
        # Admin force signature case
        if pg_conn is None and force_sign:
            cert_contents = sign_key(tmp_pubkey.name, username, '+12h',
                                     username)
            remove(tmp_pubkey.name)
            return cert_contents
        # Else, if db is down it fails.
        elif pg_conn is None:
            remove(tmp_pubkey.name)
            return message
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute(
            'SELECT * FROM USERS WHERE SSH_KEY=(%s) AND NAME=lower(%s)',
            (pubkey, username))
        user = cur.fetchone()
        if user is None:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return 'Error : User or Key absent, add your key again.'

        if username != user[0] or realname != user[1]:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return 'Error : (username, realname) couple mismatch.'

        status = user[2]
        expiry = user[6]
        principals = get_principals(user[7], username, shell=True)

        if status > 0:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return "Status: %s" % STATES[user[2]]

        cert_contents = sign_key(tmp_pubkey.name,
                                 username,
                                 expiry,
                                 principals,
                                 db_cursor=cur)

        remove(tmp_pubkey.name)
        pg_conn.commit()
        cur.close()
        pg_conn.close()
        return cert_contents
예제 #5
0
    def PUT(self):
        """
        This function permit to add or update a ssh public key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return response_render(message, http_code='401 Unauthorized')

        payload = data2map()

        if 'username' in payload:
            username = payload['username']
        else:
            return response_render(
                'Error: No username option given.',
                http_code='400 Bad Request')

        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return response_render(
                "Error: Username doesn't match pattern %s" \
                % username_pattern.pattern,
                http_code='400 Bad Request')


        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        realname_pattern = re_compile(
            r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"
            r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"'
            r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', IGNORECASE)
        if realname_pattern.match(realname) is None:
            return response_render(
                "Error: Realname doesn't match pattern",
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        if pg_conn is None:
            remove(tmp_pubkey.name)
            return response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute('SELECT * FROM USERS WHERE NAME=(%s)', (username,))
        user = cur.fetchone()

        # CREATE NEW USER
        if user is None:
            cur.execute('INSERT INTO USERS VALUES \
                ((%s), (%s), (%s), (%s), (%s), (%s), (%s), (%s))', \
                (username, realname, 2, 0, pubkey_fingerprint, pubkey, '+12h', ''))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Create user=%s. Pending request.' % username,
                http_code='201 Created')
        else:
            # Check if realname is the same
            cur.execute('SELECT * FROM USERS WHERE NAME=(%s) AND REALNAME=lower((%s))', \
                (username, realname))
            if cur.fetchone() is None:
                pg_conn.commit()
                cur.close()
                pg_conn.close()
                remove(tmp_pubkey.name)
                return response_render(
                    'Error : (username, realname) couple mismatch.',
                    http_code='401 Unauthorized')
            # Update entry into database
            cur.execute('UPDATE USERS SET SSH_KEY=(%s), SSH_KEY_HASH=(%s), STATE=2, EXPIRATION=0 \
                WHERE NAME=(%s)', (pubkey, pubkey_fingerprint, username))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render('Update user=%s. Pending request.' % username)
예제 #6
0
    def POST(self):
        """
        Ask to sign pub key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.

            # Optionnal
            admin_force=true|false
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return response_render(message, http_code='401 Unauthorized')

        # Check if user is an admin and want to force signature when db fail
        force_sign = False

        # LDAP ADMIN authentication
        is_admin_auth, _ = ldap_authentification(admin=True)

        payload = data2map()

        if is_admin_auth and SERVER_OPTS['admin_db_failover'] \
            and 'admin_force' in payload and payload['admin_force'].lower() == 'true':
            force_sign = True

        # Get username
        if 'username' in payload:
            username = payload['username']
        else:
            return response_render(
                'Error: No username option given. Update your CASSH >= 1.3.0',
                http_code='400 Bad Request')
        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return response_render(
                "Error: Username doesn't match pattern %s" \
                % username_pattern.pattern,
                http_code='400 Bad Request')

        # Get realname
        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        # Admin force signature case
        if pg_conn is None and force_sign:
            cert_contents = TOOLS.sign_key(tmp_pubkey.name, username, '+12h', username)
            remove(tmp_pubkey.name)
            return response_render(cert_contents, content_type='application/octet-stream')
        # Else, if db is down it fails.
        elif pg_conn is None:
            remove(tmp_pubkey.name)
            return response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute('SELECT * FROM USERS WHERE SSH_KEY=(%s) AND NAME=lower(%s)', (pubkey, username))
        user = cur.fetchone()
        if user is None:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Error : User or Key absent, add your key again.',
                http_code='400 Bad Request')

        if username != user[0] or realname != user[1]:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Error : (username, realname) couple mismatch.',
                http_code='401 Unauthorized')

        status = user[2]
        expiry = user[6]
        principals = get_principals(user[7], username, shell=True)

        if status > 0:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render("Status: %s" % STATES[user[2]])

        cert_contents = TOOLS.sign_key(tmp_pubkey.name, username, expiry, principals, db_cursor=cur)

        remove(tmp_pubkey.name)
        pg_conn.commit()
        cur.close()
        pg_conn.close()
        return response_render(
            cert_contents,
            content_type='application/octet-stream')
예제 #7
0
파일: server.py 프로젝트: nbeguier/cassh
    def PUT(self):
        """
        This function permit to add or update a ssh public key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return response_render(message, http_code='401 Unauthorized')

        payload = data2map()

        if 'username' in payload:
            username = payload['username']
        else:
            return response_render(
                'Error: No username option given.',
                http_code='400 Bad Request')

        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return response_render(
                "Error: Username doesn't match pattern %s" \
                % username_pattern.pattern,
                http_code='400 Bad Request')


        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        realname_pattern = re_compile("^([a-zA-Z0-9\.]+@[a-zA-Z0-9\.]+)$")
        if realname_pattern.match(realname) is None:
            return response_render(
                "Error: Realname doesn't match pattern",
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        if pg_conn is None:
            remove(tmp_pubkey.name)
            return response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute('SELECT * FROM USERS WHERE NAME=(%s)', (username,))
        user = cur.fetchone()

        # CREATE NEW USER
        if user is None:
            cur.execute('INSERT INTO USERS VALUES \
                ((%s), (%s), (%s), (%s), (%s), (%s), (%s), (%s))', \
                (username, realname, 2, 0, pubkey_fingerprint, pubkey, '+12h', ''))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Create user=%s. Pending request.' % username,
                http_code='201 Created')
        else:
            # Check if realname is the same
            cur.execute('SELECT * FROM USERS WHERE NAME=(%s) AND REALNAME=lower((%s))', \
                (username, realname))
            if cur.fetchone() is None:
                pg_conn.commit()
                cur.close()
                pg_conn.close()
                remove(tmp_pubkey.name)
                return response_render(
                    'Error : (username, realname) couple mismatch.',
                    http_code='401 Unauthorized')
            # Update entry into database
            cur.execute('UPDATE USERS SET SSH_KEY=(%s), SSH_KEY_HASH=(%s), STATE=2, EXPIRATION=0 \
                WHERE NAME=(%s)', (pubkey, pubkey_fingerprint, username))
            pg_conn.commit()
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render('Update user=%s. Pending request.' % username)
예제 #8
0
파일: server.py 프로젝트: nbeguier/cassh
    def POST(self):
        """
        Ask to sign pub key.
        /client
            username=xxxxxx          => Unique username. Used by default to connect on server.
            [email protected] => This LDAP/AD user.

            # Optionnal
            admin_force=true|false
        """
        # LDAP authentication
        is_auth, message = ldap_authentification()
        if not is_auth:
            return response_render(message, http_code='401 Unauthorized')

        # Check if user is an admin and want to force signature when db fail
        force_sign = False

        # LDAP ADMIN authentication
        is_admin_auth, _ = ldap_authentification(admin=True)

        payload = data2map()

        if is_admin_auth and SERVER_OPTS['admin_db_failover'] \
            and 'admin_force' in payload and payload['admin_force'].lower() == 'true':
            force_sign = True

        # Get username
        if 'username' in payload:
            username = payload['username']
        else:
            return response_render(
                'Error: No username option given. Update your CASSH >= 1.3.0',
                http_code='400 Bad Request')
        username_pattern = re_compile("^([a-z]+)$")
        if username_pattern.match(username) is None or username == 'all':
            return response_render(
                "Error: Username doesn't match pattern %s" \
                % username_pattern.pattern,
                http_code='400 Bad Request')

        # Get realname
        if 'realname' in payload:
            realname = unquote_plus(payload['realname'])
        else:
            return response_render(
                'Error: No realname option given.',
                http_code='400 Bad Request')

        # Get public key
        if 'pubkey' in payload:
            pubkey = unquote_custom(payload['pubkey'])
        else:
            return response_render(
                'Error: No pubkey given.',
                http_code='400 Bad Request')
        tmp_pubkey = NamedTemporaryFile(delete=False)
        tmp_pubkey.write(bytes(pubkey, 'utf-8'))
        tmp_pubkey.close()

        pubkey_fingerprint = get_fingerprint(tmp_pubkey.name)
        if pubkey_fingerprint == 'Unknown':
            remove(tmp_pubkey.name)
            return response_render(
                'Error : Public key unprocessable',
                http_code='422 Unprocessable Entity')

        pg_conn, message = TOOLS.pg_connection()
        # Admin force signature case
        if pg_conn is None and force_sign:
            cert_contents = TOOLS.sign_key(tmp_pubkey.name, username, '+12h', username)
            remove(tmp_pubkey.name)
            return response_render(cert_contents, content_type='application/octet-stream')
        # Else, if db is down it fails.
        elif pg_conn is None:
            remove(tmp_pubkey.name)
            return response_render(message, http_code='503 Service Unavailable')
        cur = pg_conn.cursor()

        # Search if key already exists
        cur.execute('SELECT * FROM USERS WHERE SSH_KEY=(%s) AND NAME=lower(%s)', (pubkey, username))
        user = cur.fetchone()
        if user is None:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Error : User or Key absent, add your key again.',
                http_code='400 Bad Request')

        if username != user[0] or realname != user[1]:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render(
                'Error : (username, realname) couple mismatch.',
                http_code='401 Unauthorized')

        status = user[2]
        expiry = user[6]
        principals = get_principals(user[7], username, shell=True)

        if status > 0:
            cur.close()
            pg_conn.close()
            remove(tmp_pubkey.name)
            return response_render("Status: %s" % STATES[user[2]])

        cert_contents = TOOLS.sign_key(tmp_pubkey.name, username, expiry, principals, db_cursor=cur)

        remove(tmp_pubkey.name)
        pg_conn.commit()
        cur.close()
        pg_conn.close()
        return response_render(
            cert_contents,
            content_type='application/octet-stream')