1 # ===================================================================== 2 # openidSetup: W-TW OpenID 1.1 dumb-mode 'checkid_setup' method. 3 # 4 # Copyright (c) 2008,2009 Carlo Strozzi 5 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; version 2 dated June, 1991. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 # 19 # ===================================================================== 20 21 # ===================================================================== 22 # Local variables and functions 23 # ===================================================================== 24 25 cgi.group = () 26 cgi.group.literal = () 27 cgi.openid.url = () 28 29 cgi.grep.uri = () 30 31 openid_url = () 32 openid_server = () 33 openid_delegate = () 34 openid_user = () 35 36 # ===================================================================== 37 # Main program 38 # ===================================================================== 39 40 csaGetArgs POST 41 42 #~ $REMOTE_ADDR 192.168.1.2 || csaExit.fault 0036 # testing 43 44 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env 45 46 . $CSA_ROOT/lib/group-stuff.rc 47 48 ~ $'cgi.openid.url' http://* https://* || csaExit.fault 0038 49 ~ $'cgi.grep.uri' () && csaExit.fault 0066 # should not occur. 50 51 openid_url = $'cgi.openid.url' # set default. 52 53 # Make URL canonical by appending a slash if missing, 54 # or curl(1) may possibly not follow a redirection. 55 56 ~ $openid_url */ || openid_url = $openid_url/ 57 58 # New authentication not allowed if already logged-in. 59 csaTrue $CSA_AUTH_OK && csaExit.fault --back 1029 60 61 # Grant further privileges if appropriate. 62 . $CSA_ROOT/lib/group-editor.rc 63 64 # Create the OpenID table if it does not yet exist; note the lock 65 # on the Principal Lock Semaphore (PLS) as opposed than on the actual 66 # OpenID table. 67 68 csaLock $TNS_USER_TABLE || csaExit.fault 69 70 if (!csaIsFullPath --exists --quiet $CSA_ROOT/var/pages/openid+dat) { 71 maketable --input \ 72 $CSA_ROOT/lib/openid.xrf > $CSA_ROOT/var/pages/openid+dat || 73 csaExit.fault 0003 maketable 74 } 75 76 # Trying to enter an unknown OpenID URL ? If we want to allow users 77 # to self-register with their OpenIDs then unknown OpenID URLs will 78 # be allowed, and if they verify then the user will be sent to the 79 # self-registration form, possibly pre-filled with data passed by the 80 # OpenID Simple Registration Extension 1.0 protocol, as described here: 81 # http://openid.net/specs/openid-simple-registration-extension-1_0.html 82 # As a "dumb" OpenID consumer I will trigger those estensions during the 83 # 'checkid_setup' phase. 84 85 openid_user = `{grep -e '^'$'cgi.grep.uri'$tab $CSA_ROOT/var/pages/openid+dat} 86 87 if (~ $openid_user(2) () && !~ $TNS_SELFREG_AUTH *[a-z]*) { 88 csaExit.fault --back 1027 89 } 90 91 # Release the PLS ASAP, as curl(1) is yet to be run and it may take long. 92 93 csaUnlock $TNS_USER_TABLE 94 95 # Save the original (i.e. undelegated) URL provided by the user. 96 csaSession.set $openid_url 15 97 98 # "Climb" the specified URL, looking for the required "openid.server" 99 # and the optional "openid.delegate" parameters. 100 101 # Of course the following test is not bullet-proof but it should work in 102 # most cases. I only take the first 50 KBytes of data from the specified 103 # source URL, to prevent trivial DoS attacks. I could read 5 KBytes or 104 # less, but it would fail on typical CSA pages, due to the largish initial 105 # RDF block, so I need to read a bit more. Crush CR and LF characters 106 # along the way, to spot the OpenID tags more reliably with sed(1). 107 108 # Better use HTTP/1.0 or curl(1) may hang this script by keeping the 109 # connection open, depending on how the remote site works. 110 curl -0 --silent --include --retry 1 --connect-timeout 10 \ 111 --ignore-content-length --range 0-50000 \ 112 $openid_url | tr -s '[\r\n]' ' ' > $tmp1 113 114 csaStatus || csaExit.fault 0054 115 116 # Alternative way, using wget(1). Unfortunately if wget(1) is writing 117 # to a pipe and the latter is closed prematurely, as in this case, it 118 # returns "1" as opposed to SIGPIPE, making it impossible for us to 119 # understand whether the non-zero code was due to an unreachable URL or 120 # to the SIGPIPE, hence the need to act in two steps, as shown. 121 # 122 #wget -q -t 1 -T 10 --ignore-length \ 123 # -O - $openid_url | head -c 50000 | tr -s '[\r\n]' ' ' > $tmp1 124 # 125 #test -s $tmp1 || csaExit.fault 0054 126 127 echo >> $tmp1 # make sed(1) happy. 128 129 #csaExit.pcdata $tmp1 130 131 openid_args = `{sed -n -f $CSA_ROOT/lib/openid-climb.sed $tmp1} 132 133 # Expect OpenID tags to appear in any order. 134 135 if (~ $openid_args(1) openid.server) { 136 openid_server = $openid_args(2) 137 } else { 138 ~ $openid_args(3) openid.server && openid_server = $openid_args(4) 139 } 140 141 if (~ $openid_args(1) openid.delegate) { 142 openid_delegate = $openid_args(2) 143 } else { 144 ~ $openid_args(3) openid.delegate && openid_delegate = $openid_args(4) 145 } 146 147 # Let the delegated URL, if any, override the one entered by the client. 148 ~ $openid_delegate http://* https://* && openid_url = $openid_delegate 149 150 # Store a simple one-time token in session, to prevent MITM attacks 151 # across the OpenID authentication scheme. 152 153 csaSession.set $pid 16 154 155 # Send the client to the OpenID server for authentication. Note that the 156 # callback URL must carry an explicit query string so I cannot use a 157 # REST-mapped URL here, as the REST implementation of CSA reserves the 158 # explicit query string for "virtual" HTTP methods. 159 160 # Old version. Leave it in place as a reminder for a while. 161 # Current version follows. 162 # 163 #csaExit.location $openid_server'?openid.mode=checkid_setup&openid.identity='$openid_url'&openid.return_to='$CSA_RPC_URI^%3F0%3DopenidCheck%261%3D$'cgi.group'%262%3D$openid_user(2)^%263%3D$pid 164 165 # OpenID's Simple registration Extensions 1.0 166 # See http://openid.net/specs/openid-simple-registration-extension-1_0.html 167 # 168 # required parameters: none 169 # 170 # optional parameters: 171 # openid.sreg.{fullname,email,country,postcode,gender,dob,language,timezone,nickname} 172 173 csaExit.location $openid_server'?openid.mode=checkid_setup&openid.identity='$openid_url'&openid.return_to='$CSA_RPC_URI^%3F0%3DopenidCheck%261%3D$'cgi.group'%262%3D$openid_user(2)^%263%3D$pid'&openid.sreg.optional=fullname,email,country,postcode,gender,dob,language,timezone,nickname' 174 175 #EOF