diff --git a/codepot/etc/codepot.ini.in b/codepot/etc/codepot.ini.in index 6eb07ffd..42fafb43 100644 --- a/codepot/etc/codepot.ini.in +++ b/codepot/etc/codepot.ini.in @@ -338,6 +338,15 @@ svn_tag_property = "codepot:tag" ;------------------------------------------------------------------------------ svn_read_access = "member" +;------------------------------------------------------------------------------ +; Grant subversin read access to public repository if the user id and the +; password match this special credential configured. The value must be +; a userid and a password separated by a colon. For example, +; anonymous:aab08d13-942c-49bc-b6a7-5ca4408b08d6 +; This credentical takes precedence over non-anonymous svn_read_access mode. +;------------------------------------------------------------------------------ +svn_read_credential = "" + ;------------------------------------------------------------------------------ ; The length of a commit message must be as long as this value. ;------------------------------------------------------------------------------ diff --git a/codepot/etc/perl/Codepot/AccessHandler.pm b/codepot/etc/perl/Codepot/AccessHandler.pm index c24aab0b..35b5cdb0 100644 --- a/codepot/etc/perl/Codepot/AccessHandler.pm +++ b/codepot/etc/perl/Codepot/AccessHandler.pm @@ -56,27 +56,28 @@ sub get_config my $config = { login_model => $cfg->param ('login_model'), - ldap_server_uri => $cfg->param ('ldap_server_uri'), - ldap_server_protocol_version => $cfg->param ('ldap_server_protocol_version'), - ldap_auth_mode => $cfg->param ('ldap_auth_mode'), - ldap_userid_format => $cfg->param ('ldap_userid_format'), - ldap_password_format => $cfg->param ('ldap_password_format'), - ldap_admin_binddn => $cfg->param ('ldap_admin_binddn'), - ldap_admin_password => $cfg->param ('ldap_admin_password'), - ldap_userid_search_base => $cfg->param ('ldap_userid_search_base'), - ldap_userid_search_filter => $cfg->param ('ldap_userid_search_filter'), - ldap_insider_attribute_names => $cfg->param ('ldap_insider_attribute_names'), - ldap_insider_attribute_value => $cfg->param ('ldap_insider_attribute_value'), + ldap_server_uri => $cfg->param('ldap_server_uri'), + ldap_server_protocol_version => $cfg->param('ldap_server_protocol_version'), + ldap_auth_mode => $cfg->param('ldap_auth_mode'), + ldap_userid_format => $cfg->param('ldap_userid_format'), + ldap_password_format => $cfg->param('ldap_password_format'), + ldap_admin_binddn => $cfg->param('ldap_admin_binddn'), + ldap_admin_password => $cfg->param('ldap_admin_password'), + ldap_userid_search_base => $cfg->param('ldap_userid_search_base'), + ldap_userid_search_filter => $cfg->param('ldap_userid_search_filter'), + ldap_insider_attribute_names => $cfg->param('ldap_insider_attribute_names'), + ldap_insider_attribute_value => $cfg->param('ldap_insider_attribute_value'), - database_hostname => $cfg->param ('database_hostname'), - database_port => $cfg->param ("database_port"), - database_username => $cfg->param ('database_username'), - database_password => $cfg->param ('database_password'), - database_name => $cfg->param ('database_name'), - database_driver => $cfg->param ('database_driver'), - database_prefix => $cfg->param ('database_prefix'), + database_hostname => $cfg->param('database_hostname'), + database_port => $cfg->param("database_port"), + database_username => $cfg->param('database_username'), + database_password => $cfg->param('database_password'), + database_name => $cfg->param('database_name'), + database_driver => $cfg->param('database_driver'), + database_prefix => $cfg->param('database_prefix'), - svn_read_access => $cfg->param ('svn_read_access') + svn_read_access => $cfg->param('svn_read_access'), + svn_read_credential => $cfg->param('svn_read_credential') }; return $config; @@ -163,7 +164,7 @@ sub authenticate_ldap { my $attr_str = $cfg->{ldap_insider_attribute_names}; $attr_str =~ s/^\s+|\s+$//g; - my @attrs = split (/\s+/, $attr_str); + my @attrs = split(/\s+/, $attr_str); if (scalar(@attrs) > 0) { @@ -307,14 +308,15 @@ sub is_read_method $method eq "OPTIONS" || $method eq "REPORT" || $method eq "PROPFIND"; } + sub __handler { my ($r, $cfg, $dbh) = @_; my $method = uc($r->method()); - my $is_method_r = is_read_method ($method); + my $is_method_r = is_read_method($method); #my ($empty, $base, $repo, $dummy) = split ('/', $r->uri(), 4); - my @urisegs = split ('/', $r->uri()); + my @urisegs = split('/', $r->uri()); my $repo = $urisegs[2]; my $author; @@ -354,7 +356,7 @@ sub __handler if ($is_method_r) { - ($public, $errmsg) = is_project_public ($dbh, $cfg->{database_prefix}, $repo, $qc); + ($public, $errmsg) = is_project_public($dbh, $cfg->{database_prefix}, $repo, $qc); if ($public <= -1) { # failed to contact the authentication server @@ -375,6 +377,15 @@ sub __handler } return Apache2::Const::OK; } + elsif (defined($cfg->{svn_read_credential}) && $cfg->{svn_read_credential} ne '') + { + # security loop hole here. + my ($c_user, $c_pass) = split(/:/, $cfg->{svn_read_credential}); + if ($c_user ne '' && $c_pass ne '' && $c_user eq $userid && $c_pass eq $password) + { + return Apache2::Const::OK; + } + } } } @@ -419,7 +430,7 @@ sub __handler } } - ($member, $errmsg) = is_project_member ($dbh, $cfg->{database_prefix}, $repo, $userid, $qc); + ($member, $errmsg) = is_project_member($dbh, $cfg->{database_prefix}, $repo, $userid, $qc); if ($member <= -1) { $r->log_error ("Cannot check project membership - $errmsg"); diff --git a/codepot/src/codepot/controllers/main.php b/codepot/src/codepot/controllers/main.php index f67f9cd0..57bfd468 100644 --- a/codepot/src/codepot/controllers/main.php +++ b/codepot/src/codepot/controllers/main.php @@ -29,13 +29,13 @@ class Main extends Controller $user_name = $this->input->post('user_name'); $user_pass = $this->input->post('user_pass'); - if ($this->login->authenticate ($user_name, $user_pass) === FALSE) + if ($this->login->authenticate($user_name, $user_pass) === FALSE) { print 'error - ' . $this->login->getErrorMessage(); } else { - $settings = $this->users->fetchSettings ($user_name); + $settings = $this->users->fetchSettings($user_name); if ($settings !== FALSE) $this->login->setUserSettings ($settings); print 'ok'; } @@ -67,7 +67,7 @@ class Main extends Controller if($this->form_validation->run()) { - if ($this->login->authenticate ($user_name, $user_pass) === FALSE) + if ($this->login->authenticate($user_name, $user_pass) === FALSE) { $data['message'] = $this->login->getErrorMessage(); $data['user_name'] = $user_name; diff --git a/codepot/src/codepot/models/dbloginmodel.php b/codepot/src/codepot/models/dbloginmodel.php index 6e8a9f20..ba073cc8 100644 --- a/codepot/src/codepot/models/dbloginmodel.php +++ b/codepot/src/codepot/models/dbloginmodel.php @@ -53,8 +53,8 @@ class DbLoginModel extends LoginModel $result = $query->result (); if (empty($result)) { - $this->setErrorMessage ('invalid credential'); // no such user name $this->db->trans_rollback (); + $this->setErrorMessage ('No such user'); return FALSE; } diff --git a/codepot/src/codepot/models/ldaploginmodel.php b/codepot/src/codepot/models/ldaploginmodel.php index d053fa2c..cd32c958 100644 --- a/codepot/src/codepot/models/ldaploginmodel.php +++ b/codepot/src/codepot/models/ldaploginmodel.php @@ -10,9 +10,8 @@ class LdapLoginModel extends LoginModel function authenticate ($userid, $password) { - //$ldap = @ldap_connect ( - // CODEPOT_LDAP_SERVER_HOST, CODEPOT_LDAP_SERVER_PORT); - $ldap = @ldap_connect (CODEPOT_LDAP_SERVER_URI); + //$ldap = @ldap_connect (CODEPOT_LDAP_SERVER_HOST, CODEPOT_LDAP_SERVER_PORT); + $ldap = @ldap_connect(CODEPOT_LDAP_SERVER_URI); if ($ldap === FALSE) { $this->setErrorMessage ("Can't connect to LDAP server"); @@ -31,7 +30,7 @@ class LdapLoginModel extends LoginModel $f_basedn = $this->formatString (CODEPOT_LDAP_USERID_SEARCH_BASE, $userid, $password); $f_filter = $this->formatString (CODEPOT_LDAP_USERID_SEARCH_FILTER, $userid, $password); - $bind = @ldap_bind ($ldap, $f_rootdn, $f_rootpw); + $bind = @ldap_bind($ldap, $f_rootdn, $f_rootpw); if ($bind === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -39,7 +38,7 @@ class LdapLoginModel extends LoginModel return FALSE; } - $sr = @ldap_search ($ldap, $f_basedn, $f_filter, array("dn")); + $sr = @ldap_search($ldap, $f_basedn, $f_filter, array("dn")); if ($sr === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -47,23 +46,23 @@ class LdapLoginModel extends LoginModel return FALSE; } - $ec = @ldap_count_entries ($ldap, $sr); + $ec = @ldap_count_entries($ldap, $sr); if ($ec === FALSE) { - $this->setErrorMessage (ldap_error ($ldap)); + $this->setErrorMessage (ldap_error($ldap)); ldap_close ($ldap); return FALSE; } if ($ec <= 0) { - $this->setErrorMessage ('No such user'); ldap_close ($ldap); + $this->setErrorMessage ('No such user'); return FALSE; } - if (($fe = @ldap_first_entry ($ldap, $sr)) === FALSE || - ($f_userid = ldap_get_dn ($ldap, $fe)) === FALSE) + if (($fe = @ldap_first_entry($ldap, $sr)) === FALSE || + ($f_userid = ldap_get_dn($ldap, $fe)) === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); ldap_close ($ldap); @@ -72,12 +71,12 @@ class LdapLoginModel extends LoginModel } else { - $f_userid = $this->formatString (CODEPOT_LDAP_USERID_FORMAT, $userid, $password); + $f_userid = $this->formatString(CODEPOT_LDAP_USERID_FORMAT, $userid, $password); } - $f_password = $this->formatString (CODEPOT_LDAP_PASSWORD_FORMAT, $userid, $password); + $f_password = $this->formatString(CODEPOT_LDAP_PASSWORD_FORMAT, $userid, $password); - $bind = @ldap_bind ($ldap, $f_userid, $f_password); + $bind = @ldap_bind($ldap, $f_userid, $f_password); if ($bind === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -90,7 +89,7 @@ class LdapLoginModel extends LoginModel { //$filter = '(' . CODEPOT_LDAP_MAIL_ATTRIBUTE_NAME . '=*)'; $filter = '(objectClass=*)'; - $r = @ldap_read ($ldap, $f_userid, $filter, array(CODEPOT_LDAP_MAIL_ATTRIBUTE_NAME)); + $r = @ldap_read($ldap, $f_userid, $filter, array(CODEPOT_LDAP_MAIL_ATTRIBUTE_NAME)); if ($r !== FALSE) { $e = @ldap_get_entries($ldap, $r); @@ -107,12 +106,12 @@ class LdapLoginModel extends LoginModel if (CODEPOT_LDAP_INSIDER_ATTRIBUTE_NAMES != '' && CODEPOT_LDAP_INSIDER_ATTRIBUTE_VALUE != '') { $attr_str = trim(CODEPOT_LDAP_INSIDER_ATTRIBUTE_NAMES); - $attrs = preg_split ("/[[:space:]]+/", $attr_str); + $attrs = preg_split("/[[:space:]]+/", $attr_str); if (count($attrs) > 0) { $filter = '(objectClass=*)'; - $r = @ldap_read ($ldap, $f_userid, $filter, $attrs); + $r = @ldap_read($ldap, $f_userid, $filter, $attrs); if ($r !== FALSE) { /* SAMPLE LDAP RESULT @@ -171,14 +170,14 @@ class LdapLoginModel extends LoginModel //@ldap_unbind ($ldap); @ldap_close ($ldap); - return parent::__authenticate ($userid, $password, $email, $insider); + return parent::__authenticate($userid, $password, $email, $insider); } function queryUserInfo ($userid) { //$ldap = @ldap_connect ( // CODEPOT_LDAP_SERVER_HOST, CODEPOT_LDAP_SERVER_PORT); - $ldap = @ldap_connect (CODEPOT_LDAP_SERVER_URI); + $ldap = @ldap_connect(CODEPOT_LDAP_SERVER_URI); if ($ldap === FALSE) { $this->setErrorMessage ("Can't connect to LDAP server"); @@ -190,7 +189,7 @@ class LdapLoginModel extends LoginModel ldap_set_option ($ldap, LDAP_OPT_PROTOCOL_VERSION, CODEPOT_LDAP_SERVER_PROTOCOL_VERSION); } - $bind = @ldap_bind ($ldap, CODEPOT_LDAP_ADMIN_BINDDN, CODEPOT_LDAP_ADMIN_PASSWORD); + $bind = @ldap_bind($ldap, CODEPOT_LDAP_ADMIN_BINDDN, CODEPOT_LDAP_ADMIN_PASSWORD); if ($bind === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -200,10 +199,10 @@ class LdapLoginModel extends LoginModel if (CODEPOT_LDAP_AUTH_MODE == 2) { - $f_basedn = $this->formatString (CODEPOT_LDAP_USERID_SEARCH_BASE, $userid, ''); - $f_filter = $this->formatString (CODEPOT_LDAP_USERID_SEARCH_FILTER, $userid, ''); + $f_basedn = $this->formatString(CODEPOT_LDAP_USERID_SEARCH_BASE, $userid, ''); + $f_filter = $this->formatString(CODEPOT_LDAP_USERID_SEARCH_FILTER, $userid, ''); - $sr = @ldap_search ($ldap, $f_basedn, $f_filter, array("dn")); + $sr = @ldap_search($ldap, $f_basedn, $f_filter, array("dn")); if ($sr === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -211,7 +210,7 @@ class LdapLoginModel extends LoginModel return FALSE; } - $ec = @ldap_count_entries ($ldap, $sr); + $ec = @ldap_count_entries($ldap, $sr); if ($ec === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); @@ -226,8 +225,8 @@ class LdapLoginModel extends LoginModel return FALSE; } - if (($fe = @ldap_first_entry ($ldap, $sr)) === FALSE || - ($f_userid = ldap_get_dn ($ldap, $fe)) === FALSE) + if (($fe = @ldap_first_entry($ldap, $sr)) === FALSE || + ($f_userid = ldap_get_dn($ldap, $fe)) === FALSE) { $this->setErrorMessage (ldap_error ($ldap)); ldap_close ($ldap); @@ -236,7 +235,7 @@ class LdapLoginModel extends LoginModel } else { - $f_userid = $this->formatString (CODEPOT_LDAP_USERID_FORMAT, $userid, ''); + $f_userid = $this->formatString(CODEPOT_LDAP_USERID_FORMAT, $userid, ''); } $email = ''; diff --git a/codepot/src/codepot/models/loginmodel.php b/codepot/src/codepot/models/loginmodel.php index e59d14f3..6a2db3f6 100644 --- a/codepot/src/codepot/models/loginmodel.php +++ b/codepot/src/codepot/models/loginmodel.php @@ -72,7 +72,7 @@ class LoginModel extends Model $server = $_SERVER['HTTP_HOST']; $sysadmin = FALSE; - $ids = explode (',', CODEPOT_SYSADMIN_USERIDS); + $ids = explode(',', CODEPOT_SYSADMIN_USERIDS); foreach ($ids as $id) { if (trim($id) == $userid) @@ -82,6 +82,7 @@ class LoginModel extends Model } } + // big security loophole - implement a different way of session management $this->session->set_userdata ( array ( 'userid' => $userid, diff --git a/codepot/src/codepot/models/projectmodel.php b/codepot/src/codepot/models/projectmodel.php index 6d0d4b44..4835ac8f 100644 --- a/codepot/src/codepot/models/projectmodel.php +++ b/codepot/src/codepot/models/projectmodel.php @@ -496,7 +496,7 @@ class ProjectModel extends Model $recipients = ''; foreach ($query->result() as $v) { - $m = $login_model->queryUserInfo ($v->userid); + $m = $login_model->queryUserInfo($v->userid); if ($m !== FALSE && $m['email'] != '') { if (!empty($recipients)) $recipients .= ', '; diff --git a/codepot/src/config.php.in b/codepot/src/config.php.in index 4d2de76d..2894772b 100644 --- a/codepot/src/config.php.in +++ b/codepot/src/config.php.in @@ -34,6 +34,7 @@ function load_ini ($file) array ('signin_compulsory', 'boolean', FALSE), array ('code_read_access', 'string', 'anonymous'), + array ('code_read_credential', 'string', ''), array ('file_read_access', 'string', 'anonymous'), array ('https_compulsory', 'boolean', FALSE),