Example #1
0
def session_started(con, source, mac, time, ipv4=None, ipv6=None):
    """Record an address session.

    Possibly associates the session with any corresponding user session.
    """
    # # There's no one useful to return an error to, so we just close any
    # # previous open sessions, so we at least get a record that it got
    # # reopened.
    cur = con.execute('UPDATE addr_sessions SET end = ?'
                      ' WHERE source = ? AND mac = ? AND ipv4 IS ?'
                      ' AND ipv6 IS ? AND end IS NULL',
                      (time, source, mac.bytes, common.ipv4_to_bytes(ipv4),
                       common.ipv6_to_bytes(ipv6)))
    if cur.rowcount > 0:
        logger().warn(('Closed {0:d} existing {1} sessions for '
                       '{2!r} {3!r} {4!r}').format(cur.rowcount, source, mac,
                                                   ipv4, ipv6))
    cur = con.execute('SELECT id FROM user_sessions'
                      ' WHERE mac = ? AND end IS NULL', (mac.bytes,))
    row = cur.fetchone()
    if row:
        usersess = row[0]
        if cur.fetchone():
            logger().warn('More than one user session for {0!r}'.format(mac))
    else:
        usersess = None
    con.execute('INSERT INTO addr_sessions'
                ' (user_session, mac, source, ipv4, ipv6, start)'
                ' VALUES (?,?,?,?,?,?)',
                (usersess, mac.bytes, source, common.ipv4_to_bytes(ipv4),
                 common.ipv6_to_bytes(ipv6), time))
    logger().info(('Session from {2} started at {5!s}: {1!r} {3!r} {4!r}'
                    ' (matched with user session {0!s})'
                   ).format(usersess, mac, source, ipv4, ipv6, time))
Example #2
0
def session_ended(con, source, mac, time, ipv4=None, ipv6=None):
    """Record a session ending.

    If enough of the user's address sessions have ended, terminate the user
    sessions and revoke their access.
    
    Current criteria: revoke if all arp and nd sessions for the mac have ended.
    """
    # Pseudocode:
    # SELECT id, user_session FROM addr_sessions WHERE source = ? AND mac = ?
    #   AND (ipv4/6 clause)
    #   (source, mac.bytes, ipv4/6)
    # UPDATE addr_sessions SET end = ? WHERE id = ?
    #   (time, id)
    # SELECT COUNT(*) FROM addr_sessions WHERE user_session = ?
    #   AND source IN ('arp', 'nd') AND end IS NULL
    #   (user_session)
    # if count == 0:
    #   end_user_session(con, user_session)
    pass
    cur = con.execute('SELECT id, user_session FROM addr_sessions'
                      ' WHERE source = ? AND mac = ?'
                      ' AND ipv4 IS ? AND ipv6 IS ? AND end IS NULL',
                      (source, mac.bytes, common.ipv4_to_bytes(ipv4),
                       common.ipv6_to_bytes(ipv6)))
    rows = cur.fetchall()
    addr_sessions = [row[0] for row in rows]
    user_sessions = set([row[1] for row in rows])
    if len(addr_sessions) > 1:
        logger().warn(('session_ended: More than one {0} session open for'
                       ' {1!r} {2!r} {3!r}. Closing all of them'
                      ).format(source, mac, ipv4, ipv6))
    if len(user_sessions) > 1:
        logger().error('session_ended: Multiple user sessions as well.')
    for addrsess in addr_sessions:
        con.execute('UPDATE addr_sessions SET end = ? WHERE id = ?',
                    (time, addrsess))
    for usersess in user_sessions:
        if usersess is not None:
            cur = con.execute('SELECT COUNT(*) FROM addr_sessions'
                              ' WHERE user_session = ?'
                              ' AND source IN (\'arp\', \'nd\') AND end IS NULL',
                              (usersess,))
            if cur.fetchone()[0] == 0:
                end_user_session(con, usersess)