author | Michael Krelin <hacker@klever.net> | 2014-06-30 18:29:32 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2014-06-30 18:29:32 (UTC) |
commit | 44963f7c48fa76b2bbf1cc8b63b84519c0cc4c6e (patch) (unidiff) | |
tree | 341198729a5462ef560c06ae8a93bdb3c653acf2 | |
parent | 9d4ae3e240e8d82a5e500c1bfbf3b4e8a43c62c6 (diff) | |
download | clipperz-44963f7c48fa76b2bbf1cc8b63b84519c0cc4c6e.zip clipperz-44963f7c48fa76b2bbf1cc8b63b84519c0cc4c6e.tar.gz clipperz-44963f7c48fa76b2bbf1cc8b63b84519c0cc4c6e.tar.bz2 |
reject zero A from the client (as per CLP-01-017)
-rw-r--r-- | backend/node/src/clipperz.js | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/backend/node/src/clipperz.js b/backend/node/src/clipperz.js index 72b6c9f..842de31 100644 --- a/backend/node/src/clipperz.js +++ b/backend/node/src/clipperz.js | |||
@@ -144,64 +144,66 @@ var CLIPPERZ = module.exports = function(CONFIG) { | |||
144 | "SELECT u_id, u_srp_s, u_srp_v FROM clipperz.theuser WHERE u_name=$1", | 144 | "SELECT u_id, u_srp_s, u_srp_v FROM clipperz.theuser WHERE u_name=$1", |
145 | [ppp.C], function(e,r) { | 145 | [ppp.C], function(e,r) { |
146 | if(e) return cb(e); | 146 | if(e) return cb(e); |
147 | if(!r.rowCount) return cb(null,{u_id:null,u_srp_s:n123,u_srp_v:n123}); | 147 | if(!r.rowCount) return cb(null,{u_id:null,u_srp_s:n123,u_srp_v:n123}); |
148 | cb(null,r.rows[0]); | 148 | cb(null,r.rows[0]); |
149 | }) }, | 149 | }) }, |
150 | otp: ['u',function(cb,r) { | 150 | otp: ['u',function(cb,r) { |
151 | if(!req.session.otp) return cb(); | 151 | if(!req.session.otp) return cb(); |
152 | if(req.session.u!=r.u.u_id) return cb(new Error('user/OTP mismatch')); | 152 | if(req.session.u!=r.u.u_id) return cb(new Error('user/OTP mismatch')); |
153 | PG.Q( | 153 | PG.Q( |
154 | "UPDATE clipperz.theotp AS otp" | 154 | "UPDATE clipperz.theotp AS otp" |
155 | +" SET" | 155 | +" SET" |
156 | +" otps_id=CASE WHEN s.otps_code='REQUESTED' THEN (" | 156 | +" otps_id=CASE WHEN s.otps_code='REQUESTED' THEN (" |
157 | +" SELECT ss.otps_id FROM clipperz.otpstatus AS ss WHERE ss.otps_code='USED'" | 157 | +" SELECT ss.otps_id FROM clipperz.otpstatus AS ss WHERE ss.otps_code='USED'" |
158 | +" ) ELSE otp.otps_id END," | 158 | +" ) ELSE otp.otps_id END," |
159 | +" otp_utime=current_timestamp" | 159 | +" otp_utime=current_timestamp" |
160 | +" FROM clipperz.otpstatus AS s, clipperz.theotp AS o" | 160 | +" FROM clipperz.otpstatus AS s, clipperz.theotp AS o" |
161 | +" WHERE" | 161 | +" WHERE" |
162 | +" o.otp_id=otp.otp_id AND otp.otps_id=s.otps_id" | 162 | +" o.otp_id=otp.otp_id AND otp.otps_id=s.otps_id" |
163 | +" AND otp.otp_id=$1 AND otp.u_id=$2" | 163 | +" AND otp.otp_id=$1 AND otp.u_id=$2" |
164 | +" RETURNING o.otps_id!=otp.otps_id AS yes, o.otp_ref", | 164 | +" RETURNING o.otps_id!=otp.otps_id AS yes, o.otp_ref", |
165 | [ req.session.otp, req.session.u ], | 165 | [ req.session.otp, req.session.u ], |
166 | function(e,r) { | 166 | function(e,r) { |
167 | if(e) return cb(e); | 167 | if(e) return cb(e); |
168 | if(!r.rowCount) return cb(new Error('no OTP found')); | 168 | if(!r.rowCount) return cb(new Error('no OTP found')); |
169 | r=r.rows[0]; | 169 | r=r.rows[0]; |
170 | if(!r.yes) return cb(new Error('OTP is in a sorry state')); | 170 | if(!r.yes) return cb(new Error('OTP is in a sorry state')); |
171 | cb(null,{ref:r.otp_ref}); | 171 | cb(null,{ref:r.otp_ref}); |
172 | }); | 172 | }); |
173 | }] | 173 | }] |
174 | },function(e,r) { | 174 | },function(e,r) { |
175 | if(e) return cb(e); | 175 | if(e) return cb(e); |
176 | var A = BIGNUM(ppp.A,16); | ||
177 | if(A.eq(0)) return cb(new Error('Ground Zero')); | ||
176 | req.session.C = ppp.C; req.session.A = ppp.A; | 178 | req.session.C = ppp.C; req.session.A = ppp.A; |
177 | req.session.s = r.u.u_srp_s; req.session.v = r.u.u_srp_v; | 179 | req.session.s = r.u.u_srp_s; req.session.v = r.u.u_srp_v; |
178 | req.session.u = r.u.u_id; | 180 | req.session.u = r.u.u_id; |
179 | req.session.b = clipperz_random(); | 181 | req.session.b = clipperz_random(); |
180 | req.session.B = srp_k.mul(BIGNUM(req.session.v,16)).add(srp_g.powm(BIGNUM(req.session.b,16),srp_n)).toString(16); | 182 | req.session.B = srp_k.mul(BIGNUM(req.session.v,16)).add(srp_g.powm(BIGNUM(req.session.b,16),srp_n)).toString(16); |
181 | var rv = {s:req.session.s,B:req.session.B} | 183 | var rv = {s:req.session.s,B:req.session.B} |
182 | if(r.otp && r.otp.otp_ref) rv.oneTimePassword=r.otp.otp_ref; | 184 | if(r.otp && r.otp.otp_ref) rv.oneTimePassword=r.otp.otp_ref; |
183 | res.res(rv); | 185 | res.res(rv); |
184 | }); | 186 | }); |
185 | 187 | ||
186 | case 'credentialCheck': | 188 | case 'credentialCheck': |
187 | var u = clipperz_hash(BIGNUM(req.session.A,16).toString(10)+BIGNUM(req.session.B,16).toString(10)); | 189 | var u = clipperz_hash(BIGNUM(req.session.A,16).toString(10)+BIGNUM(req.session.B,16).toString(10)); |
188 | var A = BIGNUM(req.session.A,16); | 190 | var A = BIGNUM(req.session.A,16); |
189 | var S = A.mul(BIGNUM(req.session.v,16).powm(BIGNUM(u,16),srp_n)).powm(BIGNUM(req.session.b,16),srp_n); | 191 | var S = A.mul(BIGNUM(req.session.v,16).powm(BIGNUM(u,16),srp_n)).powm(BIGNUM(req.session.b,16),srp_n); |
190 | var K = clipperz_hash(S.toString(10)); | 192 | var K = clipperz_hash(S.toString(10)); |
191 | var M1 = clipperz_hash( | 193 | var M1 = clipperz_hash( |
192 | srp_hn | 194 | srp_hn |
193 | +clipperz_hash(req.session.C) | 195 | +clipperz_hash(req.session.C) |
194 | +BIGNUM(req.session.s,16).toString(10) | 196 | +BIGNUM(req.session.s,16).toString(10) |
195 | +A.toString(10) | 197 | +A.toString(10) |
196 | +BIGNUM(req.session.B,16).toString(10) | 198 | +BIGNUM(req.session.B,16).toString(10) |
197 | +K ); | 199 | +K ); |
198 | if(M1!=ppp.M1) return res.res({error:'?'}); | 200 | if(M1!=ppp.M1) return res.res({error:'?'}); |
199 | req.session.K = K; | 201 | req.session.K = K; |
200 | var M2 = clipperz_hash(A.toString(10)+M1+K.toString(16)); | 202 | var M2 = clipperz_hash(A.toString(10)+M1+K.toString(16)); |
201 | return res.res({M2:M2,connectionId:'',loginInfo:{latest:{},current:{}},offlineCopyNeeded:false,lock:'----'}); | 203 | return res.res({M2:M2,connectionId:'',loginInfo:{latest:{},current:{}},offlineCopyNeeded:false,lock:'----'}); |
202 | 204 | ||
203 | case 'oneTimePassword': return PG.Q( | 205 | case 'oneTimePassword': return PG.Q( |
204 | "UPDATE clipperz.theotp AS otp" | 206 | "UPDATE clipperz.theotp AS otp" |
205 | +" SET" | 207 | +" SET" |
206 | +" otps_id = CASE WHEN s.otps_code!='ACTIVE' THEN s.otps_id ELSE (" | 208 | +" otps_id = CASE WHEN s.otps_code!='ACTIVE' THEN s.otps_id ELSE (" |
207 | +" SELECT ss.otps_id FROM clipperz.otpstatus AS ss WHERE ss.otps_code=CASE" | 209 | +" SELECT ss.otps_id FROM clipperz.otpstatus AS ss WHERE ss.otps_code=CASE" |