1 # ===================================================================== 2 # openidCheck.awk: RPC I/O function for rpclib/openidCheck. 3 # 4 # Copyright (c) 2007,2008,2009,2010 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 # void _userproc(int mode) 23 # ===================================================================== 24 25 function _userproc(mode, value,i,a,tmp,tmp1) { 26 27 if (mode == _O_REQUEST) { # request. 28 29 # target group 30 value = _request("1",1) 31 32 # group must not be null and it may not contain the 33 # unescaped ``.'' character. 34 35 if (value != _NULL && value !~ /\./) { 36 _rcset("cgi.group",unixify(value)) 37 _rcset("cgi.group.literal",value) 38 } 39 40 # user-id will always be considered lower-case and using 41 # an e-mail should not be allowed, to prevent breaking 42 # privacy when a user-id is virtually cancelled. 43 44 if ((value=substr(tolower(_strip(_request("2"))),1,16)) && \ 45 length(value) > 4 && value ~ /^[-+_a-z0-9.]+$/) { 46 _rcset("CSA_AUTH_USER",value) 47 48 # escape grep(1) regexp chars in URL. 49 gsub(/[][\\^$.*|()]/,"\\\&",value) 50 _rcset("cgi.grep.user",value) 51 } 52 53 if ((value=_request("3")/1)) _rcset("cgi.nonce",value) 54 55 # Manage expected OpenID callback arguments from the 56 # remote server, and limit the length of each value 57 # to some appropriate size, just in case. Note that 58 # arguments returned by the remote OpenID Identity 59 # Provider have names such as "openid.mode", but the 60 # CSA sanitization process turns them to "openid_mode", 61 # so I must refer to them by their sanitized names. 62 63 _rcset("cgi.openid.mode",\ 64 substr(_request("openid_mode",1),1,64)) 65 66 _rcset("cgi.openid.assoc_handle",\ 67 _uriencode(substr(_request("openid_assoc_handle",1),1,128))) 68 69 _rcset("cgi.openid.sig",\ 70 _uriencode(substr(_request("openid_sig",1),1,128))) 71 72 _rcset("cgi.openid.signed",\ 73 _uriencode((value=substr(_request("openid_signed",1),1,256)))) 74 75 split(value,a,",") 76 77 for (i in a) { 78 79 if (a[i] == "mode" || \ 80 a[i] == "assoc_handle" || \ 81 a[i] == "sig" || \ 82 a[i] == "signed") continue # See OpenID 1.1 specs. 83 84 # Sanity check 85 else if (a[i] !~ /^(sreg\.)?[-a-zA-Z0-9_]+$/) continue 86 87 # Account for the fact that CSA library routines store 88 # CGI variable names with dots replaced by underscores. 89 # Also, since multiple underscores my be undesirable with 90 # rc(1), I squeeze any repeated dots into one single 91 # underscore, just in case. 92 93 tmp = a[i]; gsub(/\.+/,"_",tmp) 94 95 # Signed values may contain URLs, hence the increased max size. 96 # If the list of signed fields includes also fields that were 97 # individually handled further up the new value will be used 98 # and the new size will override the previous limit, but it 99 # doesn't matter. 100 101 _rcset("cgi.openid." a[i],\ 102 (value=substr(_request("openid_" tmp,1),1,256))) 103 _rcset("cgi.return_values",_uriencode(value),_NULL,_O_APPEND) 104 _rcset("cgi.return_names", a[i],_NULL,_O_APPEND) 105 106 if (tmp1 != _NULL) tmp1 = tmp1 "&" 107 tmp1 = tmp1 a[i] "=" _uriencode(value) 108 } 109 110 _rcset("cgi.regform_url", tmp1) 111 112 # openid.op_endpoint must be handled *after* the above, as 113 # as an URL it requires special care and while reflecting 114 # its literal value back to the originating server as a 115 # result of the above loop may be OK, actually calling it 116 # with curl(1) without further checks is out of question. 117 118 value = substr(_request("openid_op_endpoint",1),1,256) 119 120 if (value != _NULL && value !~ /[ \t\r\n<>]/) { 121 122 tmp = "http://" 123 124 if (sub(/^[hH][tT][tT][pP]:\/\//,"",value)); 125 else if (sub(/^[hH][tT][tT][pP][sS]:\/\//,"",value)) 126 tmp = "https://" 127 128 while (gsub(/\/\//,"/",value)); # Squeeze repeated slashes. 129 130 sub(/\/+$/,"",value) # Chop trailing slashes. 131 132 tmp1 = value 133 134 sub(/[^\/]*\/*/,"/",value) # Strip host[:port] 135 136 sub(/\/.*/,"",tmp1) # Strip /path 137 138 tmp1 = tolower(tmp1) # FQDN part 139 140 # Be paranoid regarding the URL syntax by requiring that the 141 # hostname be at least a two-component FQDN. See other paranoid 142 # HTTP library implementations for futher suggestions, like 143 # Perl's LWPx::ParanoidAgent among the others. 144 145 if (tmp1 !~ /^[-a-z0-9]+(\.[-a-z0-9]+)+/) tmp1 = _NULL 146 147 if (tmp1 == _NULL) { 148 tmp = "-" 149 value = _NULL 150 } 151 152 # Assign the resulting URL. 153 _rcset("cgi.openid.op_endpoint",tmp tmp1 value) 154 } 155 156 # The following test is necessary since the address could, 157 # at least in theory, have been set to any string by the 158 # remote user, due to how it is handled to cope with stunnel(8) 159 # and the lack of transproxy support in kernel 2.4.x. 160 161 if (_isipaddr(ENVIRON["REMOTE_ADDR"]) == _TRUE) 162 value = ENVIRON["REMOTE_ADDR"] 163 else value = "0.0.0.0" 164 165 _rcset("REMOTE_ADDR",value) 166 } 167 168 else { # response 169 170 # generic template conditionals. 171 172 ifsections() 173 } 174 } 175 176 # EOF