Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

MDL-28646 add missing authentication web service checks. Merge downlo…

…ad/upload script checks in the same lib functions. Make the download scrit return json error message. Add missing webservice lang. Minor unit test doc improvement.
  • Loading branch information...
commit 07cc3d11e2081364d5d33f4f9cec5c30b62a53a5 1 parent ec0d6ea
Jérôme Mouneyrac mouneyrac authored
1  lang/en/webservice.php
@@ -162,6 +162,7 @@
162 162 $string['service'] = 'Service';
163 163 $string['servicehelpexplanation'] = 'A service is a set of functions. A service can be accessed by all users or just specified users.';
164 164 $string['servicename'] = 'Service name';
  165 +$string['servicenotavailable'] = 'the web service is not available (it does not exist or it is disabled)';
165 166 $string['servicesbuiltin'] = 'Built-in services';
166 167 $string['servicescustom'] = 'Custom services';
167 168 $string['serviceusers'] = 'Authorised users';
118 webservice/lib.php
@@ -35,6 +35,124 @@
35 35 class webservice {
36 36
37 37 /**
  38 + * Authenticate user (used by download/upload file scripts)
  39 + * @param string $token
  40 + * @return array - contains the authenticated user, token and service objects
  41 + */
  42 + public function authenticate_user($token) {
  43 + global $DB, $CFG;
  44 +
  45 + // web service must be enabled to use this script
  46 + if (!$CFG->enablewebservices) {
  47 + throw new webservice_access_exception(get_string('enablewsdescription', 'webservice'));
  48 + }
  49 +
  50 + // Obtain token record
  51 + if (!$token = $DB->get_record('external_tokens', array('token' => $token))) {
  52 + throw new webservice_access_exception(get_string('invalidtoken', 'webservice'));
  53 + }
  54 +
  55 + // Validate token date
  56 + if ($token->validuntil and $token->validuntil < time()) {
  57 + add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('invalidtimedtoken', 'webservice'), 0);
  58 + $DB->delete_records('external_tokens', array('token' => $token->token));
  59 + throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
  60 + }
  61 +
  62 + // Check ip
  63 + if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
  64 + add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . getremoteaddr(), 0);
  65 + throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
  66 + }
  67 +
  68 + //retrieve user link to the token
  69 + $user = $DB->get_record('user', array('id' => $token->userid, 'deleted' => 0), '*', MUST_EXIST);
  70 +
  71 + // let enrol plugins deal with new enrolments if necessary
  72 + enrol_check_plugins($user);
  73 +
  74 + // setup user session to check capability
  75 + session_set_user($user);
  76 +
  77 + //assumes that if sid is set then there must be a valid associated session no matter the token type
  78 + if ($token->sid) {
  79 + $session = session_get_instance();
  80 + if (!$session->session_exists($token->sid)) {
  81 + $DB->delete_records('external_tokens', array('sid' => $token->sid));
  82 + throw new webservice_access_exception(get_string('invalidtokensession', 'webservice'));
  83 + }
  84 + }
  85 +
  86 + //Non admin can not authenticate if maintenance mode
  87 + $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user);
  88 + if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
  89 + throw new webservice_access_exception(get_string('sitemaintenance', 'admin'));
  90 + }
  91 +
  92 + //retrieve web service record
  93 + $service = $DB->get_record('external_services', array('id' => $token->externalserviceid, 'enabled' => 1));
  94 + if (empty($service)) {
  95 + // will throw exception if no token found
  96 + throw new webservice_access_exception(get_string('servicenotavailable', 'webservice'));
  97 + }
  98 +
  99 + //check if there is any required system capability
  100 + if ($service->requiredcapability and !has_capability($service->requiredcapability, get_context_instance(CONTEXT_SYSTEM), $user)) {
  101 + throw new webservice_access_exception(get_string('missingrequiredcapability', 'webservice', $service->requiredcapability));
  102 + }
  103 +
  104 + //specific checks related to user restricted service
  105 + if ($service->restrictedusers) {
  106 + $authoriseduser = $DB->get_record('external_services_users', array('externalserviceid' => $service->id, 'userid' => $user->id));
  107 +
  108 + if (empty($authoriseduser)) {
  109 + throw new webservice_access_exception(get_string('usernotallowed', 'webservice', $service->name));
  110 + }
  111 +
  112 + if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) {
  113 + throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
  114 + }
  115 +
  116 + if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) {
  117 + throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
  118 + }
  119 + }
  120 +
  121 + //only confirmed user should be able to call web service
  122 + if (empty($user->confirmed)) {
  123 + add_to_log(SITEID, 'webservice', 'user unconfirmed', '', $user->username);
  124 + throw new webservice_access_exception(get_string('usernotconfirmed', 'moodle', $user->username));
  125 + }
  126 +
  127 + //check the user is suspended
  128 + if (!empty($user->suspended)) {
  129 + add_to_log(SITEID, 'webservice', 'user suspended', '', $user->username);
  130 + throw new webservice_access_exception(get_string('usersuspended', 'webservice'));
  131 + }
  132 +
  133 + //check if the auth method is nologin (in this case refuse connection)
  134 + if ($user->auth == 'nologin') {
  135 + add_to_log(SITEID, 'webservice', 'nologin auth attempt with web service', '', $user->username);
  136 + throw new webservice_access_exception(get_string('nologinauth', 'webservice'));
  137 + }
  138 +
  139 + //Check if the user password is expired
  140 + $auth = get_auth_plugin($user->auth);
  141 + if (!empty($auth->config->expiration) and $auth->config->expiration == 1) {
  142 + $days2expire = $auth->password_expire($user->username);
  143 + if (intval($days2expire) < 0) {
  144 + add_to_log(SITEID, 'webservice', 'expired password', '', $user->username);
  145 + throw new webservice_access_exception(get_string('passwordisexpired', 'webservice'));
  146 + }
  147 + }
  148 +
  149 + // log token access
  150 + $DB->set_field('external_tokens', 'lastaccess', time(), array('id' => $token->id));
  151 +
  152 + return array('user' => $user, 'token' => $token, 'service' => $service);
  153 + }
  154 +
  155 + /**
38 156 * Add a user to the list of authorised user of a given service
39 157 * @param object $user
40 158 */
93 webservice/pluginfile.php
@@ -24,96 +24,23 @@
24 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 25 */
26 26
  27 +define('AJAX_SCRIPT', true);
27 28 define('NO_MOODLE_COOKIES', true);
28 29 require_once(dirname(dirname(__FILE__)) . '/config.php');
29 30 require_once($CFG->libdir . '/filelib.php');
  31 +require_once($CFG->dirroot . '/webservice/lib.php');
30 32
31   -$relativepath = get_file_argument();
  33 +//authenticate the user
32 34 $token = required_param('token', PARAM_ALPHANUM);
  35 +$webservicelib = new webservice();
  36 +$authenticationinfo = $webservicelib->authenticate_user($token);
33 37
34   -// web service must be enabled to use this script
35   -if (!$CFG->enablewebservices) {
36   - print_error('enablewsdescription', 'webservice');
37   -}
38   -
39   -// Obtain token record
40   -if (!$token = $DB->get_record('external_tokens', array('token'=>$token))) {
41   - print_error('invalidtoken', 'webservice');
42   -}
43   -
44   -//retrieve web service record
45   -$servicesql = 'SELECT s.*
46   - FROM {external_services} s, {external_tokens} t
47   - WHERE t.externalserviceid = s.id
48   - AND t.token = ? AND t.userid = ? AND s.enabled = 1';
49   -$service = $DB->get_record_sql($servicesql, array($token->token, $token->userid), MUST_EXIST);
50   -
51   -$enabledfiledownload = (int)$service->downloadfiles;
52   -
  38 +//check the service allows file download
  39 +$enabledfiledownload = (int) ($authenticationinfo['service']->downloadfiles);
53 40 if (empty($enabledfiledownload)) {
54   - print_error('enabledirectdownload', 'webservice');
55   -}
56   -
57   -$user = $DB->get_record('user', array('id'=>$token->userid, 'deleted'=>0), '*', MUST_EXIST);
58   -
59   -//Non admin can not authenticate if maintenance mode
60   -$hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user);
61   -if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
62   - print_error('sitemaintenance', 'admin');
63   -}
64   -
65   -// Validate token date
66   -if ($token->validuntil and $token->validuntil < time()) {
67   - add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('invalidtimedtoken', 'webservice'), 0);
68   - $DB->delete_records('external_tokens', array('token'=>$token->token));
69   - print_error('invalidtimedtoken', 'webservice');
70   -}
71   -
72   -//assumes that if sid is set then there must be a valid associated session no matter the token type
73   -if ($token->sid) {
74   - $session = session_get_instance();
75   - if (!$session->session_exists($token->sid)) {
76   - $DB->delete_records('external_tokens', array('sid'=>$token->sid));
77   - print_error('invalidtokensession', 'webservice');
78   - }
  41 + throw new webservice_access_exception(get_string('enabledirectdownload', 'webservice'));
79 42 }
80 43
81   -// Check ip
82   -if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
83   - add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".getremoteaddr(), 0);
84   - print_error('invalidiptoken', 'webservice');
85   -}
86   -
87   -//only confirmed user should be able to call web service
88   -if (empty($user->confirmed)) {
89   - add_to_log(SITEID, 'webservice', 'user unconfirmed', '', $user->username);
90   - print_error('usernotconfirmed', 'moodle', '', $user->username);
91   -}
92   -
93   -//check the user is suspended
94   -if (!empty($user->suspended)) {
95   - add_to_log(SITEID, 'webservice', 'user suspended', '', $user->username);
96   - print_error('usersuspended', 'webservice');
97   -}
98   -
99   -//check if the auth method is nologin (in this case refuse connection)
100   -if ($user->auth == 'nologin') {
101   - add_to_log(SITEID, 'webservice', 'nologin auth attempt with web service', '', $user->username);
102   - print_error('nologinauth', 'webservice');
103   -}
104   -
105   -$auth = get_auth_plugin($user->auth);
106   -
107   -if (!empty($auth->config->expiration) and $auth->config->expiration == 1) {
108   - $days2expire = $auth->password_expire($user->username);
109   - if (intval($days2expire) < 0 ) {
110   - add_to_log(SITEID, 'webservice', 'expired password', '', $user->username);
111   - print_error('passwordisexpired', 'webservice');
112   - }
113   -}
114   -
115   -// log token access
116   -$DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
117   -session_set_user($user);
118   -
  44 +//finally we can serve the file :)
  45 +$relativepath = get_file_argument();
119 46 file_pluginfile($relativepath, 0);
7 webservice/simpletest/testwebservice.php
@@ -262,12 +262,9 @@ function core_course_get_contents($client) {
262 262 $coursecontents = $client->call($function, $params);
263 263 }
264 264
265   - //TODO: some unit tests to check that generated course content data test match what
266   - // the web service function is returning.
267   -
268   - //Realistic TODO: display the content of $coursecontents in your php log and check if you obtain
  265 + //Display the content of $coursecontents in your php log and check if you obtain
269 266 //what you are expecting
270   - //varlog($coursecontents);
  267 + //error_log(print_r($coursecontents, true));
271 268 }
272 269 }
273 270
82 webservice/upload.php
@@ -25,85 +25,17 @@
25 25 define('AJAX_SCRIPT', true);
26 26 define('NO_MOODLE_COOKIES', true);
27 27 require_once(dirname(dirname(__FILE__)) . '/config.php');
28   -$token = required_param('token', PARAM_ALPHANUM);
  28 +require_once($CFG->dirroot . '/webservice/lib.php');
29 29 $filepath = optional_param('filepath', '/', PARAM_PATH);
30 30
31 31 echo $OUTPUT->header();
32 32
33   -//Non admin can not authenticate if maintenance mode
34   -$hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user);
35   -if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
36   - throw new moodle_exception('sitemaintenance', 'admin');
37   -}
38   -
39   -// web service must be enabled to use this script
40   -if (!$CFG->enablewebservices) {
41   - throw new moodle_exception('enablewsdescription', 'webservice');
42   -}
43   -// Obtain token record
44   -if (!$token = $DB->get_record('external_tokens', array('token'=>$token))) {
45   - throw new webservice_access_exception(get_string('invalidtoken', 'webservice'));
46   -}
47   -
48   -// Validate token date
49   -if ($token->validuntil and $token->validuntil < time()) {
50   - add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('invalidtimedtoken', 'webservice'), 0);
51   - $DB->delete_records('external_tokens', array('token'=>$token->token));
52   - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
53   -}
54   -
55   -//assumes that if sid is set then there must be a valid associated session no matter the token type
56   -if ($token->sid) {
57   - $session = session_get_instance();
58   - if (!$session->session_exists($token->sid)) {
59   - $DB->delete_records('external_tokens', array('sid'=>$token->sid));
60   - throw new webservice_access_exception(get_string('invalidtokensession', 'webservice'));
61   - }
62   -}
63   -
64   -// Check ip
65   -if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
66   - add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".getremoteaddr(), 0);
67   - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
68   -}
69   -
70   -$user = $DB->get_record('user', array('id'=>$token->userid, 'deleted'=>0), '*', MUST_EXIST);
71   -
72   -//check if the auth method is nologin (in this case refuse connection)
73   -if ($auth=='nologin') {
74   - add_to_log(SITEID, 'webservice', 'nologin auth attempt with web service', '', $user->username);
75   - throw new webservice_access_exception(get_string('nologinauth', 'webservice'));
76   -}
77   -
78   -//only confirmed user should be able to call web service
79   -if (empty($user->confirmed)) {
80   - add_to_log(SITEID, 'webservice', 'user unconfirmed', '', $user->username);
81   - throw new webservice_access_exception(get_string('usernotconfirmed', 'moodle', $user->username));
82   -}
83   -
84   -//check the user is suspended
85   -if (!empty($user->suspended)) {
86   - add_to_log(SITEID, 'webservice', 'user suspended', '', $user->username);
87   - throw new webservice_access_exception(get_string('usersuspended', 'webservice'));
88   -}
89   -
90   -// check if credentials have expired
91   -$auth = get_auth_plugin($user->auth);
92   -
93   -if (!empty($auth->config->expiration) and $auth->config->expiration == 1) {
94   - $days2expire = $auth->password_expire($user->username);
95   - if (intval($days2expire) < 0 ) {
96   - add_to_log(SITEID, 'webservice', 'expired password', '', $user->username);
97   - throw new webservice_access_exception(get_string('passwordisexpired', 'webservice'));
98   - }
99   -}
100   -
101   -// log token access
102   -$DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
  33 +//authenticate the user
  34 +$token = required_param('token', PARAM_ALPHANUM);
  35 +$webservicelib = new webservice();
  36 +$authenticationinfo = $webservicelib->authenticate_user($token);
103 37
104   -// let enrol plugins deal with new enrolments if necessary
105   -enrol_check_plugins($user);
106   -session_set_user($user);
  38 +//check the user can manage his own files (can upload)
107 39 $context = get_context_instance(CONTEXT_USER, $USER->id);
108 40 require_capability('moodle/user:manageownfiles', $context);
109 41
@@ -183,7 +115,7 @@
183 115 $file_record->filepath = $filepath;
184 116 $file_record->itemid = 0;
185 117 $file_record->license = $CFG->sitedefaultlicense;
186   - $file_record->author = fullname($user);;
  118 + $file_record->author = fullname($authenticationinfo['user']);;
187 119 $file_record->source = '';
188 120 $stored_file = $fs->create_file_from_pathname($file_record, $file->filepath);
189 121 $results[] = $file_record;

0 comments on commit 07cc3d1

Please sign in to comment.
Something went wrong with that request. Please try again.