2005-01-19 09:50:24 +08:00
|
|
|
/*
|
2013-03-17 07:45:21 +08:00
|
|
|
* ZoneMinder regular expression class implementation, $Date$, $Revision$
|
2008-07-25 17:33:23 +08:00
|
|
|
* Copyright (C) 2001-2008 Philip Coombes
|
2005-01-19 09:50:24 +08:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zm.h"
|
|
|
|
#include "zm_db.h"
|
|
|
|
|
|
|
|
#include "zm_user.h"
|
|
|
|
|
2011-06-21 17:19:10 +08:00
|
|
|
#include <stdio.h>
|
2011-08-03 19:31:06 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2011-06-21 17:19:10 +08:00
|
|
|
|
2005-01-19 09:50:24 +08:00
|
|
|
User::User()
|
|
|
|
{
|
|
|
|
username[0] = password[0] = 0;
|
|
|
|
enabled = false;
|
2005-10-17 05:11:44 +08:00
|
|
|
stream = events = control = monitors = system = PERM_NONE;
|
2005-01-19 09:50:24 +08:00
|
|
|
monitor_ids = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
User::User( MYSQL_ROW &dbrow )
|
|
|
|
{
|
2005-10-17 05:11:44 +08:00
|
|
|
int index = 0;
|
|
|
|
strncpy( username, dbrow[index++], sizeof(username) );
|
|
|
|
strncpy( password, dbrow[index++], sizeof(password) );
|
|
|
|
enabled = (bool)atoi( dbrow[index++] );
|
|
|
|
stream = (Permission)atoi( dbrow[index++] );
|
|
|
|
events = (Permission)atoi( dbrow[index++] );
|
|
|
|
control = (Permission)atoi( dbrow[index++] );
|
|
|
|
monitors = (Permission)atoi( dbrow[index++] );
|
|
|
|
system = (Permission)atoi( dbrow[index++] );
|
2005-03-21 03:32:18 +08:00
|
|
|
monitor_ids = 0;
|
2005-10-17 05:11:44 +08:00
|
|
|
char *monitor_ids_str = dbrow[index++];
|
2005-01-19 09:50:24 +08:00
|
|
|
if ( monitor_ids_str && *monitor_ids_str )
|
|
|
|
{
|
2005-03-21 03:32:18 +08:00
|
|
|
monitor_ids = new int[strlen(monitor_ids_str)];
|
2005-01-19 09:50:24 +08:00
|
|
|
int n_monitor_ids = 0;
|
|
|
|
const char *ptr = monitor_ids_str;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int id = 0;
|
|
|
|
while( isdigit( *ptr ) )
|
|
|
|
{
|
|
|
|
id *= 10;
|
|
|
|
id += *ptr-'0';
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
if ( id )
|
|
|
|
{
|
|
|
|
monitor_ids[n_monitor_ids++] = id;
|
|
|
|
if ( !*ptr )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while ( !isdigit( *ptr ) )
|
|
|
|
ptr++;
|
|
|
|
} while( *ptr );
|
|
|
|
monitor_ids[n_monitor_ids] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
User::~User()
|
|
|
|
{
|
|
|
|
delete monitor_ids;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool User::canAccess( int monitor_id )
|
|
|
|
{
|
|
|
|
if ( !monitor_ids )
|
|
|
|
{
|
|
|
|
return( true );
|
|
|
|
}
|
|
|
|
for ( int i = 0; monitor_ids[i]; i++ )
|
|
|
|
{
|
|
|
|
if ( monitor_ids[i] == monitor_id )
|
|
|
|
{
|
|
|
|
return( true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to load a user from username and password
|
|
|
|
User *zmLoadUser( const char *username, const char *password )
|
|
|
|
{
|
2010-11-11 20:22:35 +08:00
|
|
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
2005-10-20 23:42:41 +08:00
|
|
|
|
|
|
|
if ( password )
|
|
|
|
{
|
|
|
|
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", username, password );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", username );
|
|
|
|
}
|
2005-01-19 09:50:24 +08:00
|
|
|
|
|
|
|
if ( mysql_query( &dbconn, sql ) )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
2005-01-19 09:50:24 +08:00
|
|
|
exit( mysql_errno( &dbconn ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
MYSQL_RES *result = mysql_store_result( &dbconn );
|
|
|
|
if ( !result )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
2005-01-19 09:50:24 +08:00
|
|
|
exit( mysql_errno( &dbconn ) );
|
|
|
|
}
|
|
|
|
int n_users = mysql_num_rows( result );
|
|
|
|
|
|
|
|
if ( n_users != 1 )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Warning( "Unable to authenticate user %s", username );
|
2005-01-19 09:50:24 +08:00
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
MYSQL_ROW dbrow = mysql_fetch_row( result );
|
|
|
|
|
|
|
|
User *user = new User( dbrow );
|
2008-07-14 22:43:47 +08:00
|
|
|
Info( "Authenticated user '%s'", user->getUsername() );
|
2005-01-19 09:50:24 +08:00
|
|
|
|
2005-11-30 01:51:06 +08:00
|
|
|
mysql_free_result( result );
|
|
|
|
|
2005-01-19 09:50:24 +08:00
|
|
|
return( user );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to validate an authentication string
|
|
|
|
User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
|
|
|
{
|
2013-03-17 07:45:21 +08:00
|
|
|
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
2010-11-11 20:11:06 +08:00
|
|
|
#ifdef HAVE_GCRYPT_H
|
|
|
|
// Special initialisation for libgcrypt
|
|
|
|
if ( !gcry_check_version( GCRYPT_VERSION ) )
|
|
|
|
{
|
|
|
|
Fatal( "Unable to initialise libgcrypt" );
|
|
|
|
}
|
|
|
|
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
|
|
|
|
gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 );
|
|
|
|
#endif // HAVE_GCRYPT_H
|
|
|
|
|
2005-01-19 09:50:24 +08:00
|
|
|
const char *remote_addr = "";
|
|
|
|
if ( use_remote_addr )
|
|
|
|
{
|
|
|
|
remote_addr = getenv( "REMOTE_ADDR" );
|
|
|
|
if ( !remote_addr )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Warning( "Can't determine remote address, using null" );
|
2005-01-19 09:50:24 +08:00
|
|
|
remote_addr = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-14 22:43:47 +08:00
|
|
|
Debug( 1, "Attempting to authenticate user from auth string '%s'", auth );
|
2010-11-11 20:22:35 +08:00
|
|
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
2005-10-17 05:11:44 +08:00
|
|
|
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1" );
|
2005-01-19 09:50:24 +08:00
|
|
|
|
|
|
|
if ( mysql_query( &dbconn, sql ) )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
2005-01-19 09:50:24 +08:00
|
|
|
exit( mysql_errno( &dbconn ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
MYSQL_RES *result = mysql_store_result( &dbconn );
|
|
|
|
if ( !result )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
2005-01-19 09:50:24 +08:00
|
|
|
exit( mysql_errno( &dbconn ) );
|
|
|
|
}
|
|
|
|
int n_users = mysql_num_rows( result );
|
|
|
|
|
|
|
|
if ( n_users < 1 )
|
|
|
|
{
|
2008-07-14 22:43:47 +08:00
|
|
|
Warning( "Unable to authenticate user" );
|
2005-01-19 09:50:24 +08:00
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) )
|
|
|
|
{
|
|
|
|
const char *user = dbrow[0];
|
|
|
|
const char *pass = dbrow[1];
|
|
|
|
|
|
|
|
char auth_key[512] = "";
|
|
|
|
char auth_md5[32+1] = "";
|
2013-08-28 20:22:41 +08:00
|
|
|
size_t md5len = 16;
|
2013-03-17 07:45:21 +08:00
|
|
|
unsigned char md5sum[md5len];
|
2005-01-19 09:50:24 +08:00
|
|
|
|
|
|
|
time_t now = time( 0 );
|
|
|
|
int max_tries = 2;
|
|
|
|
|
|
|
|
for ( int i = 0; i < max_tries; i++, now -= (60*60) )
|
|
|
|
{
|
|
|
|
struct tm *now_tm = localtime( &now );
|
|
|
|
|
|
|
|
snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
|
2005-10-20 23:42:41 +08:00
|
|
|
config.auth_hash_secret,
|
2005-01-19 09:50:24 +08:00
|
|
|
user,
|
|
|
|
pass,
|
|
|
|
remote_addr,
|
|
|
|
now_tm->tm_hour,
|
|
|
|
now_tm->tm_mday,
|
|
|
|
now_tm->tm_mon,
|
|
|
|
now_tm->tm_year
|
|
|
|
);
|
|
|
|
|
2013-07-25 23:49:55 +08:00
|
|
|
#if HAVE_DECL_MD5
|
2005-01-19 09:50:24 +08:00
|
|
|
MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum );
|
2013-03-17 07:45:21 +08:00
|
|
|
#elif HAVE_DECL_GNUTLS_FINGERPRINT
|
|
|
|
gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) };
|
|
|
|
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len );
|
|
|
|
#endif
|
2005-01-19 09:50:24 +08:00
|
|
|
auth_md5[0] = '\0';
|
2013-03-17 07:45:21 +08:00
|
|
|
for ( unsigned int j = 0; j < md5len; j++ )
|
2005-01-19 09:50:24 +08:00
|
|
|
{
|
2005-01-27 04:55:50 +08:00
|
|
|
sprintf( &auth_md5[2*j], "%02x", md5sum[j] );
|
2005-01-19 09:50:24 +08:00
|
|
|
}
|
2008-07-14 22:43:47 +08:00
|
|
|
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s'", auth_key, auth_md5 );
|
2005-01-19 09:50:24 +08:00
|
|
|
|
|
|
|
if ( !strcmp( auth, auth_md5 ) )
|
|
|
|
{
|
|
|
|
// We have a match
|
|
|
|
User *user = new User( dbrow );
|
2008-07-14 22:43:47 +08:00
|
|
|
Info( "Authenticated user '%s'", user->getUsername() );
|
2005-01-19 09:50:24 +08:00
|
|
|
return( user );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-14 07:44:44 +08:00
|
|
|
#else // HAVE_DECL_MD5
|
2008-07-14 22:43:47 +08:00
|
|
|
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
2008-02-14 07:44:44 +08:00
|
|
|
#endif // HAVE_DECL_MD5
|
2005-01-19 09:50:24 +08:00
|
|
|
return( 0 );
|
|
|
|
}
|