[Sugar-devel] [PATCH Browse] Add Single Sign On support

Sascha Silbe sascha-pgp at silbe.org
Mon Jan 31 17:41:44 EST 2011


A special client certificate will be created on first start-up (after
installation resp. update). This certificate can be used to identify and
authenticate a user to web sites that ask for it. No personally identifiable
information is included in the certificate; it only identifies a user account,
not a physical person. Any binding between the user account(s) and an actual
person would need to be established out-of-band. This is similar to using
email addresses for identification and authentication purposes (an established
practice for most sites that offer services to the public).

The client certificate will be signed by a fake CA. This allows servers to
specifically ask for the client certificate created by Browse (by presenting
an "accepted CAs" list with the fake CA in it) while preventing confusing
"Select client certificate" pop-ups for other browsers. Publishing the CA
private key is not a risk because it's only used to influence the selection
of the client certificate, not for any kind of "trust" decision.

One aspect that still needs some consideration are XSS (cross-site scripting)
attacks. Content from a third party website could cause the browser to connect
to a web site using SSO with the client certificate. The browser would
automatically present the certificate to the server and thus potentially
authorise any action that the remote site tries to trigger.

Additional dependencies:
- "openssl" executable
- "certutil" and "pk12util" executables

Signed-off-by: Sascha Silbe <sascha-pgp at silbe.org>
---
 browse-sso-pseudo-ca.cert.pem    |   20 +++++++++
 browse-sso-pseudo-ca.privkey.pem |   27 ++++++++++++
 cert8.db                         |  Bin 65536 -> 65536 bytes
 key3.db                          |  Bin 0 -> 16384 bytes
 secmod.db                        |  Bin 0 -> 16384 bytes
 webactivity.py                   |   85 +++++++++++++++++++++++++++++++++----
 6 files changed, 122 insertions(+), 10 deletions(-)

diff --git a/browse-sso-pseudo-ca.cert.pem b/browse-sso-pseudo-ca.cert.pem
new file mode 100644
index 0000000..fd9691a
--- /dev/null
+++ b/browse-sso-pseudo-ca.cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQjCCAiqgAwIBAgIJAOyLmiUICdRkMA0GCSqGSIb3DQEBBQUAMB8xHTAbBgNV
+BAMTFEJyb3dzZS1TU08tUHNldWRvLUNBMB4XDTExMDEzMTE4MDMyMVoXDTM4MDYx
+NzE4MDMyMVowHzEdMBsGA1UEAxMUQnJvd3NlLVNTTy1Qc2V1ZG8tQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHbsal0Ib96+Dg9v8zmGQwtczFOLyd
+J2s5ifwF1VuUDVmm47ooDgycc6i6ULR3AoSOMu3/jvFCT5uV/wZq7sXvq2LUmiJ8
+W/fNbT9GaBoAphBoBalqrTsDROpZXsPkdkm5eN1ZtLeDDoGCX8+fYeqo61Hv2fSh
+ee7DloCYZ7TvYT0+W2hBUOvf7MFEEl/8p8/FyevB6F9Qs0RCinbUwVDdlg961Sj6
+zEa7GzgFNK1UdiyY5iXthYFdQVW1MPCgNmaIOjelMfy9YOwQv4Bs6Z4Zisi4Y0U8
+lChunySRgtckVtJfrSgGoPbT4UuLBrwtP9G7WmdOb1gv3TC9KHaZnDJvAgMBAAGj
+gYAwfjAdBgNVHQ4EFgQU2tNCUr0YkKsk+MImV5O794MKspUwTwYDVR0jBEgwRoAU
+2tNCUr0YkKsk+MImV5O794MKspWhI6QhMB8xHTAbBgNVBAMTFEJyb3dzZS1TU08t
+UHNldWRvLUNBggkA7IuaJQgJ1GQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUF
+AAOCAQEAThyMLpwfu/9UKn6nBRgFdTTmZ2VRJARtiXkT0hPe3zHKSLUKmSjxhTSN
+zcM7R+Dx3Wi2i0w8fNQcxtYima2HZQTKT4qhCPrggkXxgtnolPQ4yrFg+4DWxGFa
+Ng6uajGJmcnzt5Q+0esaxohc79caELs7Y8yzp/JuZgnXfcKYCVAha8Cg6T5e+eZo
+7XJHJPRIAuvgqobaQpX9iB8jace1UVf0h0ftnZ6FgZMjvtjONl6TqQrOWgEA3Yzb
+7pO8fVfOlEtwQzKY5Ji+aqvStM/r7/B6dAIljqsqlnhVenlWzQDKpLa4VeA5/xaE
+C8enZzxEi1IG76bB9dIELyKezcfIyQ==
+-----END CERTIFICATE-----
diff --git a/browse-sso-pseudo-ca.privkey.pem b/browse-sso-pseudo-ca.privkey.pem
new file mode 100644
index 0000000..64c135a
--- /dev/null
+++ b/browse-sso-pseudo-ca.privkey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAx27GpdCG/evg4Pb/M5hkMLXMxTi8nSdrOYn8BdVblA1ZpuO6
+KA4MnHOoulC0dwKEjjLt/47xQk+blf8Gau7F76ti1JoifFv3zW0/RmgaAKYQaAWp
+aq07A0TqWV7D5HZJuXjdWbS3gw6Bgl/Pn2HqqOtR79n0oXnuw5aAmGe072E9Plto
+QVDr3+zBRBJf/KfPxcnrwehfULNEQop21MFQ3ZYPetUo+sxGuxs4BTStVHYsmOYl
+7YWBXUFVtTDwoDZmiDo3pTH8vWDsEL+AbOmeGYrIuGNFPJQobp8kkYLXJFbSX60o
+BqD20+FLiwa8LT/Ru1pnTm9YL90wvSh2mZwybwIDAQABAoIBAFowqLl4MnRG5i4W
+xZbJxhWZQf+3BuVzXDRrSIRC1uV/nBmzRw6yO9XNIHMR6Gshwlykf6lhNY4tfkk5
+See2D+GxekJ3aj0fQlOuojzu+0Nr1mOUm+dYbCWwVuMPzjtVm0W7eS8GYS9tsfgJ
+6FVF7N9zfFyiDtWv1OCzAXjq/ZJ7c+j1AsT0Tb9TnVO9jvwKoJa54LV6LIUf98+n
+8czPaZadpGy4s7BoZ3L+yt6odnysmMs+98hpOj7rg2uGSrnU1IaKkp7CdjdIaBq4
+3vBZ8RsNlW5wa0WSQSj0hOUBn+2moJA1qUxmblkDtmOi1bRYmqPWHyuiOEUlnQM8
+ogmAfDECgYEA+Op577svjuz1o+EK8C/J87q976ZNGRWE2KwUT3O6WIQNgqY9RtF8
+4aZmkbGx0dFnMkGfW+TGXFcD3u8Hn9vP1ZdFhbP2hxdD1IF75U5D78IT0/eOfvFr
+eCkbzsoL4tsxt40Ebv8KQrubAGbShVdwxHTKCfltWZFFGnxyuvNCsSMCgYEAzRvH
+zWWb+c90Ah1v7XrvIRSCcfbaz+/tO6/kgxGezDYpHQXRUdXe2ULhRcNWuheQN7iF
+LZQqWS07bCzqkfH1f1fjh+aDKQBafjuyJwDJxf/+qkwavcbsB4Ac7fFIgrmwAx07
+2/WbjSTrYTUWpReSkCpY2dYBofYTiJbmBfLs/EUCgYEAigLv4uTlhJiLxfZz6yKE
+Fdg3kZWib8MHql8Wz8q5ynRFTWhA13A1jqOFgUiF8HDrh+jso7Xf6bjxU30yvAbT
+YHkEOhLDILnciQnWGRjhACGafs9muam/zZr1aR2Lo5enJD9S8vwDw2ZjlcBs/zOx
+OawLjaY3ZA7wwrO3pUJVewMCgYEAuaBaw1kiQIOvyfo6QgLwSE/3foyam3XYjhwy
+Ayz/OnIJ42pQdm/Ir3gHyMtwwhpxOvyUCxv895goH07HPC5usEEqeuPz8DeRroz4
+PrRH6Bo2sIkP6pENK/yWMgIcTbMfyLG8auVtUeAH5oHVbLRYwICSyRMVhy7dntBy
+fQ/NysECgYEApuEWZe38qyDAJdasWMiOnyKIc1kowgKlg3IHFmiK8ST+kTvVRbjE
+E9rnOedR2Prn414fuf5ez5LinxXad7/O/KrO4NUhEjKwwlYzp/8TWbIziZWd+SBd
+Yxb0/DwwKXLOKO18npF/n39UAjOF3nLXKpLP/iccH/FUTEQ1U486k7g=
+-----END RSA PRIVATE KEY-----
diff --git a/cert8.db b/cert8.db
index 7b3d82faf7eb6646fa0021bebcaae5f8cbd5cda7..4ef537f088faed202171be9e98f5ffb5558ce51a 100644
GIT binary patch
delta 1177
zcmZo at U}<PznPAPxztQH1J)_8EMh8Wni$<CH!TP%T|MhhBHyb+q*Q at 7XVqj1-kT;Yy
zkY-~JWnmT;aVp9$FHY4B4))g#C{8U+$=7vuWWpxMz`@AC-~fWmZVaLZP0UUPO-xz~
zn3))vm^c~Ubk9=d;JlJzz{|#|)#lOmotKf3m6ZX_s(MVj4CKUl4Gj$pjSUSg42+Eo
zqr`cQEey;I&7oX06R;T2#HfU9D<dlda}y&!gFzD`7gG}>Bg65$V at ofz{eAu5!MFPV
z#xqh3ww^g^v1hJ&wq at rZ)~nG|cq5lR-lf6EGpBgPu7EA&Of7vzZ~ymwbn>4)^*>wI
zyQA+{CtaDPR1^LEY_7dqh7`jxfehA_S!=DCU0y}T9ez^gxwGPK<d*Hte2q=<=jSKB
zTJbvY{mm~6E8iWS)-WS|%lkxIyXXwZfY<lm9IST{ivP3x{Lz!I559;G*zDreRd(fI
zz};#5RaZ5BopIYOZNX}?Hl$2v#xvEot&Opcp<4|;EHF#!urgn2_-Ajz8-e`|IWOl)
zcAeOf>}oSbBX7RS#HQ;iVVC09YOpQ%cKM-qH`^Xv`-{7y(*5!y^zRz%)hL at e$0(nP
znUR5Uabtr)eVu_UFy3YPSj1RFZe4Z?+AA?(waSk}YT=W2e{bg6G}XW#B(2QiVc^z)
zRl!2#C4|#Y6H<EM0U0RF!fL?G$oPM9$Zo-UV3hdD^ytlz-~B&Ct8O`~1Z%0uv-H$J
z6_(u2O5sbw_wE~>^4Q8XQ{!W+N$=Ui*6t5J-p$z7?PF7OMdsKwrI~BnQ&~>=cP- at j
z^`Oc1W7EwSQ@&W7+L-XW;o6bJC^NowS%#f6Pk!D$#qQ#3sbd{6 at 2^V<?6yumvw8Wa
zyfn`1we^Q)a0V!5A6W3xF7D^EjJHMZDqlR9UO!mXcFSq%-wt`@%;Q at F!@sn<znwd;
zwQ;iYz8mMv;wG=;Iv2&raJT37yUBZM!_Q6eE^s!Q at npuntksvcoPYiPLsbcrYTs(D
zX%(SWm0 at QYPA%ECBlLmgf3X(s<IB at +T)KnU-Y+}&^%9G|lIy&)$4{KZn!^|o*@#dU
z-TbGBg;$D;!NT6ruE18>Y at TVVexUwYz14d0dagjc@uDj*w=**^FfxcTFkrQfL5qQb
gcng^cW<(A)28L>&kqicvh5`nBY|NYQty2mF0EP;@^Z)<=

delta 72
zcmV-O0Jr~ufCPYm1duxc46!`KKLHSv0YD)H)-wDuvoS#YF0(*D+5 at xvas&+)2mm-g
eK|XLj8#bObWiL at L%`Uet%`UOgw=T2It}{`H7aEQL

diff --git a/key3.db b/key3.db
new file mode 100644
index 0000000000000000000000000000000000000000..b0e3d3a7505bdf237e5dca676300af0db907025e
GIT binary patch
literal 16384
zcmeI$do<MB9suwkGb2n4MKirrl*W4~c{E`>%9{vzjxk=1VK9=%6d|uv5*fxsLZQg<
zDvx2B<DKJCDyLA9<27=6P!TuX`^WwJu6543XRZBRYp?Hj?Y-Cj?)CX+ueBi|X%YlM
zf)E5Bgdm9 at CA1NO1b(FT0SW)7__6+T0`@ciT!P^1bym>X at gI3T*7vNBzdeNieV at O*
zFK7q^fB+Bx0zd!=00AHX1b_e#00KbZpCTX(eMNmi&7kT~<)~~_w)h1Rn#cu_H4s1m
z2mk>f00e*l5C8&yr2q_)HVmbmq5G)V+uNwv(tS>Q(^QNI5H1eBh{FmY6%$Ppm&61%
zA_QQ#t#Bzgky-y_f$dkWjz(*07}u&VH~R_-2*Bguoo16u!66pyR}36N0ta&~p>LFU
zo#-=z<~Wzo1I_K5q6=E|viVpFcl3jwuZ8>~6GlbGT)xp5XT)EkEj%Ue=%IZkly~^O
zopO<=Ew!){G|OW9vf`7scYV3x8?~!WK|`&aL0a;oO!Ks)e~%N^`mpSh<1J5%{S;en
z^DU2bSaEC at e``_`W2iDO>qSPD*rS}R>k1!ZcxBCxM%Q#cj`QmBt=!)n9#dz#7osY8
zsrio!37Mw49BfyvsG9M~o}CV^8b_>1n-ZwO`5u at 1x?=Vh?nLIwh3}?wSAB9m>!?Oj
zvR5sgBt^ID=_MK-r`k0zb#L8mrypU;#VjhGO6ObtHm_0dj(q7{9UhQ0adcAs?97Ai
z%<<Qz@^A5VU!oR{JoR*w^>=_Cj#m|gOZgPbT&=lP1ee>R+F1XGI_t|7Yf}v8<#3~e
zyCX*D<jxWG8_RBX`e(d at +g>z8U8aul8)w#(=C&TUzNXw&R2EtBfNI)f#gvx9amCvO
z^^4><E_5ShQmbAcx1<`aRwZ{wc{Z5HD6q;MYs?a1M8~ut#h>v{%`Hw>cPbpkWRt57
z8ZW#HEhR2qos7%hVe_qmP?8m+U-;@-SjqVgYl{clvB=!&fYS`$6j{~b^a#=XTg^@U
zF at tF|duC)=2RbLHuub*;7+T||R$$A!UqV8-t<r-cr2-+6e;hJzwyF4(DkE?@b;5&O
ze<JddCp{oohGizXe}Q0A>b8maGDKP_t&fFhT5fx2og7rvwt35P`P*~7b=|Ykw%tkd
z64Tz9V(fAy_~9G_JMz_Rj-Fwk;@jTylC7)Aj<Qbw1{^XC&lDF6!Mi3W-W%YJHoo7C
z!+sbOv=HgtK#Z;05LVOwWFICqYe9|2kl{K$<0!4BAS|~Raz5|2x*JA+C9_iYtFL>N
zN&3sgy~l20I*zHi2S+&0DOP3>W#lXA<>uEEjnsPZuF?JJ;~TUd#;B+Do=sC{+2{Io
z91S22w2`A9L_Do9F>U9hTyIXPTVSaQ5YPp>@^ukkVG|{Y+o%;vp5MXtH#hzH(e*i(
ztTdI*4!^N`G!*SY8yz~-kGM1MRJH at o_G<5*N>=XAV1;{%uf at acuM~dHj)gc8NQVqu
z>FN=DqjtD~DW|j6;uS$>M;M+lnn`J#`dZFwp}&J$eT=*<O2s>QEnRYX!L`^ixCNnk
z;@#?0)N+!pEd_n<Saygl&rPOtbg{??xyQ>U{(0_~q>*IQ2LJih1xXI4CC>oC_G#K>
zWg|B1E}MWk#*_|{yelN-ozpH`%WE-PoV!ad`mVNXdUIKWp}n>$TPPND+E2dAtO<Yr
z<kDg{(nUm=ZRy5Nc#iFzYwo!3Mv=PaM88MLH^?3ty`AuJ_&NFaY0fWoZAE2wq$$Om
z{6J^iTRF14v#YGLt<A%22ko_-h9c4r+348eQRc*&x;<W01??Ua(QS~g`uxXkVSK4>
zMSTgnW;K_rNNSlC*oSFx*2`F#8?~<42;)aOU0 at WydT~Hu4Hhw(m{wKU>L at 4QE+bZd
z5z$fE>Rn9mS1~!I=6lm~a)8>V$-4Mh_wYbSI>ii8g`wfu2~mL`Jk2Aw^v_=+#4+?s
zf1ARvLpe3O%T#AOg4&Dw6Ti>Ce!aMMfa#5^ecYzq#NHpEld^&sa?KQTE*WpYif_!L
z-)XR|IU|^GS%bfJ`A<U|R at RyjWxnlwx!2QNS%&LUZ=n8B|7}o-gg>H`a_=zAc*fa-
zHxX|3Fk-~HraoT$d>pYapEPr4_W1kZPd6jydDml^el_n&NAz6%3AVFib6n$1#Fg89
zZC$h6DWYw)v0-ZXQ?BjEbyU<4_S at s5joY;m2k)H-S7uJ`<6k)MPH?EjEfgH`P1e;a
zR$poMoResYrB2`2n%en*Y=Y0k2IcR)8uxs!;~?=KR;Xa{$s3D{LQN|A1C1_z*0hsq
zBe-U4cut-Mt%@3MZm_#c6~Qu}xY(nG)=p5;@uSkbNK_R%i5doz65yUwS&m`mieeHx
zJoc!4>O08hVWIziDNKth<X7j=e7*|gT7lNo2`16$XK10`DrA2jasbTHCzO7Q7W7Z~
zrvUc^0zd!=00AHX1b_e#00KY&2mk>f00jPbf$x9izcx4<2mk>f00e*l5C8%|00;m9
OAOHk_01)`U5cn73-h|@-

literal 0
HcmV?d00001

diff --git a/secmod.db b/secmod.db
new file mode 100644
index 0000000000000000000000000000000000000000..5e5f69659d2a3dc807fa6a4eea8734eb0556ed0b
GIT binary patch
literal 16384
zcmeI&u}Z^07{Kw*R!Rq{E^Z<R4!0Hh0KuUy5|l!Hfi$_4(3q4Y1s!}0N5N-ub8 at J!
zA$rMGv<MCkrO5w-<L<t at e0TZHC!NDUL|P)dPa+3)D0?D1wyT?TR|C7=B-%~iEV)hh
z+1=9S>ZteBZR62(_u2Tl9Ebn{2q1s}0tg_000IagfB*srAb<b at 2q1s}0tg_000Iag
zfWWp0wB&Vv*?aCSd)sm&?tuUT2q1s}0tg_000IagfWY4bI-=xd?Txr^3q`iM<k97L
ztj at E_6j_j}kv|-(lfgh;<k2EEcGp9gXK^x(lETw{twK{&qr$|=ji<GmncJ^PX~OF~
z^0e#w(L}2_4W^~17V{{mOjAOyCd0KlZiD~5noA|N-sdM*`OIWzrVNW at UL|=}uef*k
okL^>>UiH|vAMxAoy}c6%Ab<b at 2q1s}0tg_000Iag at ZSYK03j$ussI20

literal 0
HcmV?d00001

diff --git a/webactivity.py b/webactivity.py
index d744ab1..eed2f44 100644
--- a/webactivity.py
+++ b/webactivity.py
@@ -15,15 +15,17 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-import os
 import logging
 from gettext import gettext as _
+import os
+import subprocess
 
 import gobject
 gobject.threads_init()
 
 import gtk
 import base64
+import random
 import time
 import shutil
 import sqlite3
@@ -49,7 +51,7 @@ from sugar.graphics.icon import Icon
 from sugar.graphics.toolbarbox import ToolbarButton
 from sugar import mime
 
-PROFILE_VERSION = 2
+PROFILE_VERSION = 3
 
 _profile_version = 0
 _profile_path = os.path.join(activity.get_activity_root(), 'data/gecko')
@@ -64,8 +66,9 @@ if _profile_version < PROFILE_VERSION:
     if not os.path.exists(_profile_path):
         os.mkdir(_profile_path)
 
-    shutil.copy('cert8.db', _profile_path)
-    os.chmod(os.path.join(_profile_path, 'cert8.db'), 0660)
+    for file_name in ['cert8.db', 'key3.db', 'secmod.db']:
+        shutil.copy(file_name, _profile_path)
+        os.chmod(os.path.join(_profile_path, file_name), 0660)
 
     f = open(_version_file, 'w')
     f.write(str(PROFILE_VERSION))
@@ -129,6 +132,52 @@ def _seed_xs_cookie():
         _logger.debug('seed_xs_cookie: Updated cookie successfully')
 
 
+def _create_sso_certificate():
+    """
+    Ensure X.509 client certificate suitable for authentication exists.
+
+    We ship the private key of a fake CA to sign the key with. This allows
+    us to specifically "ask" for this particular client certificate by adding
+    the public key of the fake CA on the server side, so it gets sent as part
+    of the "accepted / trusted CA" list during TLS handshake. Publishing the
+    CA private key is not a risk because it's only used to influence the
+    selection of the client certificate, not for any kind of "trust" decision.
+    """
+    cert_nickname = 'Browse-SSO-User'
+    if subprocess.call(['certutil', '-L', '-d', _profile_path, '-n',
+                        cert_nickname]) == 0:
+        return
+
+    data_path = os.path.join(activity.get_activity_root(), 'data')
+    key_file_name = os.path.join(data_path, 'privkey.pem')
+    cert_file_name = os.path.join(data_path, 'cert.pem')
+    cert_req_file_name = os.path.join(data_path, 'certreq.pem')
+    p12_file_name = os.path.join(data_path, 'combined.p12')
+    user_name = profile.get_nick_name()
+    escaped_user_name = user_name.replace('/', '\\/').replace('=', '\\=')
+
+    def tighten_umask():
+        os.umask(0077)
+
+    subprocess.check_call(['openssl', 'req', '-out', cert_req_file_name,
+                           '-new', '-newkey', 'rsa:2048', '-nodes', '-keyout',
+                           key_file_name, '-subj', '/CN=' + escaped_user_name,
+                           '-utf8', '-batch'],
+                          preexec_fn=tighten_umask)
+    subprocess.check_call(['certutil', '-C', '-m',
+                           str(random.randint(1, 2**31-2)), '-a', '-i',
+                           cert_req_file_name, '-o', cert_file_name, '-c',
+                           'Browse-SSO-Pseudo-CA', '-d', _profile_path,
+                           '-v', '999'])
+    subprocess.check_call(['openssl', 'pkcs12', '-export', '-nodes',
+                           '-password', 'pass:a', '-in', cert_file_name,
+                           '-inkey', key_file_name, '-name', cert_nickname,
+                           '-out', p12_file_name], preexec_fn=tighten_umask)
+    subprocess.check_call(['pk12util', '-i', p12_file_name, '-d',
+                           _profile_path, '-K', '', '-W', 'a'],
+                          preexec_fn=tighten_umask)
+
+
 import hulahop
 hulahop.set_app_version(os.environ['SUGAR_BUNDLE_VERSION'])
 hulahop.startup(_profile_path)
@@ -136,9 +185,15 @@ hulahop.startup(_profile_path)
 from xpcom import components
 
 
+def _set_char_preference(name, value):
+    cls = components.classes["@mozilla.org/preferences-service;1"]
+    prefService = cls.getService(components.interfaces.nsIPrefService)
+    branch = prefService.getBranch('')
+    branch.setCharPref(name, value)
+
+
 def _set_accept_languages():
-    ''' Set intl.accept_languages based on the locale
-    '''
+    """Set intl.accept_languages preference based on the locale"""
 
     lang = locale.getdefaultlocale()[0]
     if not lang:
@@ -148,12 +203,20 @@ def _set_accept_languages():
 
     # e.g. es-uy, es
     pref = lang[0] + "-" + lang[1].lower()  + ", " + lang[0]
-    cls = components.classes["@mozilla.org/preferences-service;1"]
-    prefService = cls.getService(components.interfaces.nsIPrefService)
-    branch = prefService.getBranch('')
-    branch.setCharPref('intl.accept_languages', pref)
+    _set_char_preference('intl.accept_languages', pref)
     logging.debug('LANG set')
 
+
+def _set_client_certificate_policy():
+    """Set preference to select client certificate automatically.
+
+    Popping up a dialog that most users don't understand is bad UI design.
+    Instead present the "best match" to the server.
+    """
+    _set_char_preference('security.default_personal_cert',
+                         'Select Automatically')
+
+
 from browser import TabbedView
 from browser import Browser
 from webtoolbar import PrimaryToolbar
@@ -187,6 +250,8 @@ class WebActivity(activity.Activity):
 
         _set_accept_languages()
         _seed_xs_cookie()
+        _set_client_certificate_policy()
+        _create_sso_certificate()
 
         # don't pick up the sugar theme - use the native mozilla one instead
         cls = components.classes['@mozilla.org/preferences-service;1']
-- 
1.7.2.3



More information about the Sugar-devel mailing list