1 # =====================================================================
2 # rpxLogIn: W-TW RPX login processor.
3 #
4 # Copyright (c) 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 TNS_GROUP_HOME = ()
26
27 HTTP_AUTHORIZATION = () # *Always* clear any old auth.
28
29 cgi.group = ()
30 cgi.group.literal = ()
31
32 # The single argument returned by the "signin" step of the RPX protocol.
33 cgi.rpx.token = ()
34
35 openid_user = ()
36
37 # =====================================================================
38 # Main program
39 # =====================================================================
40
41 csaGetArgs GET POST
42
43 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
44 #~ $REMOTE_ADDR 192.168.1.2 || csaExit.fault 401 0013
45
46 . $CSA_ROOT/lib/group-stuff.rc
47
48 # Abide by the RPX specs. The authentication failure page can
49 # be sent after group metadata has been loaded, not earlier.
50 # This is also why this method needs to accept also POST.
51 # See https://rpxnow.com/docs#token_url .
52
53 ~ $'cgi.rpx.token' () && csaExit.needauth
54
55 # Better use HTTP/1.0 or curl(1) may hang this script by keeping the
56 # connection open, depending on how the remote site works.
57 csaSystem --return curl -0 -s -d 'apiKey='$TNS_RPX_API(1) \
58 -d 'token='$'cgi.rpx.token' -d 'format=xml' $TNS_RPX_API(3)
59
60 if (!~ $CSA_STATUS 0) {
61 echo -- ------------------------------------ >> $CSA_SYSERR
62 cat -n $CSA_SYSOUT >> $CSA_SYSERR
63
64 # if (csaIsFullPath --exists --quiet \
65 # $CSA_TPL_ROOT/tw-nav-back.txt) {
66 # # custom "back" action template.
67 # tpl.include.nav.next = $CSA_TPL_ROOT/tw-nav-back.txt
68 # } else {
69 # # default "back" action template.
70 # tpl.include.nav.next = $tw_dstem/tw-nav-back.txt
71 # }
72
73 tpl.include.tw.msg = $CSA_SYSERR
74
75 csaExit.fault --back 1008
76 }
77
78 # Example RPX error response (usually on one single line):
79 #
80 #
81 #
82 #
83 #
84 #
85 # Example RPX positive response (usually on one single line):
86 #
87 #
88 #
89 #
90 # 1971-06-19
91 # johndoe
92 # johndoe@example.com
93 # male
94 # http://www.example.com/jdoe/
95 # johnd
96 # MyOpenID
97 # http://www.example.com/jdoe/
98 #
99 #
100 #
101 # Another example, when logging-in via Google.
102 #
103 #
104 #
105 #
106 # Italy
107 #
108 # john.smith
109 # john.smith@gmail.com
110 # https://www.google.com/accounts/o8/id?id=aiToAWKbAsL8NQXsTTs54gZ5s7E1tkkm12iNOJ8
111 #
112 # John
113 # Smith
114 # John Smith
115 #
116 # john.smith
117 # Google
118 # john.smith@gmail.com
119 #
120 #
121
122 #csaExit.pcdata $CSA_SYSOUT
123
124 csaAwkCmd RPX2rc.awk
125 $CSA_RESULT < $CSA_SYSOUT > $tmp1
126
127 #csaExit.pcdata $tmp1
128
129 . $tmp1
130
131 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
132
133 ~ $'cgi.rpx.fault' () || csaExit.fault --back 1045 $'cgi.rpx.fault'
134
135 # New authentication not allowed if already logged-in.
136 csaTrue $CSA_AUTH_OK && csaExit.fault --back 1029
137
138 # Grant further privileges if appropriate.
139 . $CSA_ROOT/lib/group-editor.rc
140
141 # Create the OpenID table if it does not yet exist; note the lock
142 # on the Principal Lock Semaphore (PLS) as opposed than on the actual
143 # OpenID table.
144
145 csaLock $TNS_USER_TABLE || csaExit.fault
146
147 if (!csaIsFullPath --exists --quiet $CSA_ROOT/var/pages/openid+dat) {
148 maketable --input \
149 $CSA_ROOT/lib/openid.xrf > $CSA_ROOT/var/pages/openid+dat ||
150 csaExit.fault 0003 maketable
151 }
152
153 # Check whether the specified user has got an
154 # OpenID-enabled account with us.
155
156 if (!~ $'cgi.rpx.uri.grep' ()) {
157 openid_user = `{grep -e '^'$'cgi.rpx.uri.grep'$tab \
158 $CSA_ROOT/var/pages/openid+dat}
159 }
160
161 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
162
163 # Turn next line into !~ for testing with an already known OpenID account.
164 if (~ $openid_user(2) ()) {
165
166 #TNS_SELFREG_AUTH=guest; ~ $REMOTE_ADDR 192.168.1.2 && TNS_SELFREG_AUTOASK=true
167 if (~ $TNS_SELFREG_AUTH *[a-z]* && csaTrue $TNS_SELFREG_AUTOASK) {
168
169 # Users that have successfully proved their identidy with OpenID
170 # but who are unknown to us are sent to the registration form, if
171 # self-registration is allowed.
172
173 # The call to 'showStatic' for this particular action will be non-
174 # RESTful, due to the need to possibly pass several arguments on
175 # the URL, which would make a RESTful rewrite quite difficult.
176
177 csaExit.location $CSA_RPC_URI'?0=showStatic&x-csa-lang='$CSA_LANG^'&1='$'cgi.group'^'&2=tw-reg-form&'$'cgi.rpx.regform_url'
178
179 } else {
180 csaSession.set - 15 # clear the supplied OpenID URL
181 csaExit.needauth
182 }
183 }
184
185 # The client is known to TW and she has succesfully authenticated
186 # through OpenID.
187
188 csaSession.set $openid_user(1) 15 immediate
189
190 # The next steps are quite similar to those performed by 'logIn'.
191
192 ~ $#TNS_GROUP_HOME 1 2 || csaExit.fault 0041 TNS_GROUP_HOME # required
193
194 # Abide by the TW specs.
195 ~ $TNS_GROUP_HOME(2) () &&
196 TNS_GROUP_HOME = ($TNS_GROUP_HOME(1) $TNS_GROUP_HOME(1))
197
198 # The authCheck function is application-specific, and must be provided
199 # by the application programmer. We need to pass it the authentication
200 # data posted by the user, which was not known when 'authCheck' was
201 # called by 'weblib.rc', so we must call it again after 'csaGetArgs'.
202
203 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
204
205 # Force authentication data before calling 'authCheck --open-id'.
206 CSA_AUTH_USER = $openid_user(2)
207
208 authCheck --open-id --return # || csaExit.needauth
209
210 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
211
212 # Set new auth, after passing the authorization check.
213 HTTP_AUTHORIZATION='Basic '^`{
214 echo -n $CSA_AUTH_USER:$CSA_AUTH_PW | swu-encdec -e -b
215 }
216
217 csaPrintMsg 0014 # Log the event.
218
219 #~ $REMOTE_ADDR 192.168.1.2 && csaExit.env
220
221 # Take the user to the last failed authentication if applicable.
222 if (~ $CSA_SESSION(18) http* /*) {
223 csaSession.set - 18
224 if (csaIsInteractive) {
225 if (~ $CSA_SESSION(18) /$CSA_ID/*) {
226 csaExit.location $CSA_CGI_STEM$CSA_SESSION(18)
227 } else csaExit.location $CSA_SESSION(18)
228 }
229 }
230
231 # Else take the user to the welcome page.
232 csaExit.location \
233 $CSA_RPC_URI/$CSA_LANG/$'cgi.group'/$TNS_GROUP_HOME(2)
234
235 #EOF