aboutsummaryrefslogtreecommitdiffstats
path: root/src/ephy-nss-glue.c
diff options
context:
space:
mode:
authorXan Lopez <xan@gnome.org>2009-08-26 16:44:28 +0800
committerXan Lopez <xan@gnome.org>2009-08-26 16:45:38 +0800
commiteea4e5155ed3102ee21c57958a29603ed0f5166f (patch)
treea491d714dd8c7bc61c5a00eaf74dbff952e808c1 /src/ephy-nss-glue.c
parentec783faa3c1737dfd80fd53a8113bbb3aa1c06a0 (diff)
downloadgsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar.gz
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar.bz2
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar.lz
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar.xz
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.tar.zst
gsoc2013-epiphany-eea4e5155ed3102ee21c57958a29603ed0f5166f.zip
Import passwords from the ephy/gecko profile on first run.
This feature requires NSS, so NSS is added as an optional dependency, enabled by default. Can be disabled with --disable-nss, but then passwords won't be imported.
Diffstat (limited to 'src/ephy-nss-glue.c')
-rw-r--r--src/ephy-nss-glue.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/ephy-nss-glue.c b/src/ephy-nss-glue.c
new file mode 100644
index 000000000..a5f58cc06
--- /dev/null
+++ b/src/ephy-nss-glue.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2009 Igalia S.L.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Portions of this file based on Chromium code.
+ * License block as follows:
+ *
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * The LICENSE file from Chromium can be found in the LICENSE.chromium
+ * file.
+ */
+
+#include "config.h"
+
+#include "ephy-nss-glue.h"
+
+#include "ephy-file-helpers.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <pk11sdr.h>
+
+static gboolean nss_initialized = FALSE;
+static PK11SlotInfo *db_slot = NULL;
+
+gboolean ephy_nss_glue_init ()
+{
+ char *config_dir, *modspec;
+ SECStatus rv;
+
+ config_dir = g_build_filename (ephy_dot_dir (),
+ "mozilla", "epiphany",
+ NULL);
+ rv = NSS_Init (config_dir);
+
+ if (rv < 0) {
+ g_free (config_dir);
+ return FALSE;
+ }
+
+ modspec = g_strdup_printf ("configDir='%s' tokenDescription='Firefox NSS database' "
+ "flags=readOnly", config_dir);
+ db_slot = SECMOD_OpenUserDB (modspec);
+ g_free (config_dir);
+ g_free (modspec);
+
+ if (!db_slot)
+ return FALSE;
+
+ nss_initialized = TRUE;
+
+ return TRUE;
+}
+
+void ephy_nss_glue_close ()
+{
+ if (db_slot) {
+ PK11_FreeSlot (db_slot);
+ db_slot = NULL;
+ }
+
+ NSS_Shutdown ();
+
+ nss_initialized = FALSE;
+}
+
+typedef struct SDRResult
+{
+ SECItem keyid;
+ SECAlgorithmID alg;
+ SECItem data;
+} SDRResult;
+
+static SEC_ASN1Template g_template[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) },
+ { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) },
+ { 0 }
+};
+
+static SECStatus
+unpadBlock(SECItem *data, int blockSize, SECItem *result)
+{
+ SECStatus rv = SECSuccess;
+ int padLength;
+ int i;
+
+ result->data = 0;
+ result->len = 0;
+
+ /* Remove the padding from the end if the input data */
+ if (data->len == 0 || data->len % blockSize != 0) { rv = SECFailure; goto loser; }
+
+ padLength = data->data[data->len-1];
+ if (padLength > blockSize) { rv = SECFailure; goto loser; }
+
+ /* verify padding */
+ for (i=data->len - padLength; (uint32)i < data->len; i++) {
+ if (data->data[i] != padLength) {
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ result->len = data->len - padLength;
+ result->data = (unsigned char *)PORT_Alloc(result->len);
+ if (!result->data) { rv = SECFailure; goto loser; }
+
+ PORT_Memcpy(result->data, data->data, result->len);
+
+ if (padLength < 2) {
+ return SECWouldBlock;
+ }
+
+loser:
+ return rv;
+}
+
+static SECStatus
+pk11Decrypt (PK11SlotInfo *slot, PLArenaPool *arena,
+ CK_MECHANISM_TYPE type, PK11SymKey *key,
+ SECItem *params, SECItem *in, SECItem *result)
+{
+ PK11Context *ctx = 0;
+ SECItem paddedResult;
+ SECStatus rv;
+
+ paddedResult.len = 0;
+ paddedResult.data = 0;
+
+ ctx = PK11_CreateContextBySymKey (type, CKA_DECRYPT, key, params);
+ if (!ctx) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ paddedResult.len = in->len;
+ paddedResult.data = (unsigned char*)PORT_ArenaAlloc (arena, paddedResult.len);
+
+ rv = PK11_CipherOp (ctx, paddedResult.data,
+ (int*)&paddedResult.len, paddedResult.len,
+ in->data, in->len);
+ if (rv != SECSuccess)
+ goto loser;
+
+ PK11_Finalize(ctx);
+
+ /* Remove the padding */
+ rv = unpadBlock (&paddedResult, PK11_GetBlockSize(type, 0), result);
+ if (rv)
+ goto loser;
+
+loser:
+ if (ctx)
+ PK11_DestroyContext (ctx, PR_TRUE);
+
+ return rv;
+}
+
+static SECStatus
+PK11SDR_DecryptWithSlot (PK11SlotInfo *slot, SECItem *data, SECItem *result, void *cx)
+{
+ SECStatus rv = SECSuccess;
+ PK11SymKey *key = NULL;
+ CK_MECHANISM_TYPE type;
+ SDRResult sdrResult;
+ SECItem *params = NULL;
+ SECItem possibleResult = { (SECItemType)0, NULL, 0 };
+ PLArenaPool *arena = NULL;
+
+ arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (!arena) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Decode the incoming data */
+ memset (&sdrResult, 0, sizeof sdrResult);
+ rv = SEC_QuickDERDecodeItem (arena, &sdrResult, g_template, data);
+ if (rv != SECSuccess)
+ goto loser; /* Invalid format */
+
+ /* Get the parameter values from the data */
+ params = PK11_ParamFromAlgid (&sdrResult.alg);
+ if (!params) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Use triple-DES (Should look up the algorithm) */
+ type = CKM_DES3_CBC;
+ key = PK11_FindFixedKey (slot, type, &sdrResult.keyid, cx);
+ if (!key) {
+ rv = SECFailure;
+ } else {
+ rv = pk11Decrypt (slot, arena, type, key, params,
+ &sdrResult.data, result);
+ }
+
+ loser:
+ if (arena)
+ PORT_FreeArena (arena, PR_TRUE);
+
+ if (key)
+ PK11_FreeSymKey(key);
+
+ if (params)
+ SECITEM_ZfreeItem(params, PR_TRUE);
+
+ if (possibleResult.data)
+ SECITEM_ZfreeItem(&possibleResult, PR_FALSE);
+
+ return rv;
+}
+
+char * ephy_nss_glue_decrypt (const unsigned char *data, gsize length)
+{
+ char *plain = NULL;
+ SECItem request, reply;
+ SECStatus result;
+
+ result = PK11_Authenticate (db_slot, PR_TRUE, NULL);
+ if (result != SECSuccess)
+ return NULL;
+
+ request.data = (unsigned char*)data;
+ request.len = length;
+ reply.data = NULL;
+ reply.len = 0;
+
+ result = PK11SDR_DecryptWithSlot (db_slot, &request, &reply, NULL);
+ if (result == SECSuccess)
+ plain = g_strndup ((const char*)reply.data, reply.len);
+
+ SECITEM_FreeItem (&reply, PR_FALSE);
+
+ return plain;
+}
+