Skip to content

Commit

Permalink
Import passwords from the ephy/gecko profile on first run.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Xan Lopez committed Aug 26, 2009
1 parent ec783fa commit eea4e51
Show file tree
Hide file tree
Showing 6 changed files with 611 additions and 3 deletions.
27 changes: 27 additions & 0 deletions LICENSE.chromium
@@ -0,0 +1,27 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 changes: 21 additions & 0 deletions configure.ac
Expand Up @@ -277,6 +277,26 @@ AM_CONDITIONAL([ENABLE_SEED],[test "$enable_seed" = "yes"])

AC_SUBST([EPIPHANY_FEATURES])

# ***
# NSS
# ***

AC_MSG_CHECKING([whether NSS support is requested])
AC_ARG_ENABLE([nss],
[AS_HELP_STRING([--enable-nss], [Enable NSS support (default: enabled)])],
[], [enable_nss=yes])
AC_MSG_RESULT([$enable_nss])

if test "$enable_nss" = "yes"; then
EPIPHANY_FEATURES="$EPIPHANY_FEATURES nss"
PKG_CHECK_MODULES([NSS], [nss])

AC_DEFINE([ENABLE_NSS], [1], [Define to compile with NSS support])
fi

AM_CONDITIONAL([ENABLE_NSS],[test "$enable_nss" = "yes"])
AC_SUBST([EPIPHANY_FEATURES])

# *******************
# Additional features
# *******************
Expand Down Expand Up @@ -482,5 +502,6 @@ Epiphany was configured with the following options:
NetworkManager support : $enable_network_manager
GObject introspection : $enable_introspection
Seed support : $enable_seed
NSS support : $enable_nss
Build tests : $enable_tests
"
16 changes: 16 additions & 0 deletions src/Makefile.am
Expand Up @@ -140,6 +140,18 @@ libephymain_la_SOURCES += \
libephymain_la_CFLAGS += $(SEED_CFLAGS)
endif # ENABLE_SEED

if ENABLE_NSS
NOINST_H_FILES += \
ephy-nss-glue.h \
$(NULL)

libephymain_la_SOURCES += \
ephy-nss-glue.c
$(NULL)

libephymain_la_CFLAGS += $(NSS_CFLAGS)
endif # ENABLE_NSS

epiphany_SOURCES = ephy-main.c

epiphany_CPPFLAGS = \
Expand Down Expand Up @@ -181,6 +193,10 @@ if ENABLE_SEED
epiphany_LDADD += $(SEED_LIBS)
endif # ENABLE_SEED

if ENABLE_NSS
epiphany_LDADD += $(NSS_LIBS)
endif # ENABLE_NSS

if ENABLE_NETWORK_MANAGER
epiphany_LDADD += \
$(NETWORK_MANAGER_LIBS)
Expand Down
259 changes: 259 additions & 0 deletions 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;
}

29 changes: 29 additions & 0 deletions src/ephy-nss-glue.h
@@ -0,0 +1,29 @@
/*
* 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.
*
*/

#ifndef EPHY_NSS_GLUE_H
#define EPHY_NSS_GLUE_H

#include <glib.h>

gboolean ephy_nss_glue_init (void);
void ephy_nss_glue_close (void);
char * ephy_nss_glue_decrypt (const unsigned char *, gsize);

#endif

0 comments on commit eea4e51

Please sign in to comment.