Skip to content

Commit

Permalink
support new-style private key format fields
Browse files Browse the repository at this point in the history
The LastPass plugins now support multiline fields (besides Notes)
if the field is part of a known note template.  This has been used
to capture the embedded newlines in ascii-armored private SSH keys
with the ssh-key note type.

Until now lpass only supported ssh keys stored on a single line,
so add the ability to parse these kinds of strings to enable
support for keys created in the newer plugins.

Signed-off-by: Bob Copeland <[email protected]>
  • Loading branch information
Bob Copeland committed Apr 26, 2017
1 parent 75bcbcb commit 1ae6957
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
49 changes: 40 additions & 9 deletions blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,7 @@ void account_assign_share(struct blob *blob, struct account *account,
struct account *notes_expand(struct account *acc)
{
struct account *expand;
struct field *field;
struct field *field = NULL;
char *start, *lf, *colon, *name, *value;
struct attach *attach, *tmp;
char *line = NULL;
Expand All @@ -1157,19 +1157,48 @@ struct account *notes_expand(struct account *acc)
if (strncmp(acc->note, "NoteType:", 9))
return NULL;

enum note_type note_type = NOTE_TYPE_NONE;
lf = strchr(acc->note + 9, '\n');
if (lf) {
_cleanup_free_ char *type = xstrndup(acc->note + 9, lf - (acc->note + 9));
note_type = notes_get_type_by_name(type);
}

for (start = acc->note; ; ) {
lf = strchrnul(start, '\n');
if (lf - start < 0)
lf = NULL;
if (lf - start <= 0)
name = value = NULL;
lf = strchr(start, '\n');
if (!lf || lf == start)
goto skip;

line = xstrndup(start, lf - start);
colon = strchr(line, ':');
if (!colon)
if (colon) {
name = xstrndup(line, colon - line);
value = xstrdup(colon + 1);
}

/*
* Append non-keyed strings to existing field.
* If no field, skip.
*/
if (!name) {
if (field)
xstrappendf(&field->value, "\n%s", line);
goto skip;
}

/*
* If this is a known notetype, append any non-existent
* keys to the existing field. For example, Proc-Type
* in the ssh private key field goes into private key,
* not a Proc-Type field.
*/
if (note_type != NOTE_TYPE_NONE &&
!note_has_field(note_type, name) && field) {
xstrappendf(&field->value, "\n%s", line);
goto skip;
*colon = '\0';
name = line;
value = colon + 1;
}

if (!strcmp(name, "Username"))
expand->username = xstrdup(value);
else if (!strcmp(name, "Password"))
Expand All @@ -1190,6 +1219,8 @@ struct account *notes_expand(struct account *acc)
list_add(&field->list, &expand->field_head);
}
skip:
free(value);
free(name);
free(line);
line = NULL;
if (!lf || !*lf)
Expand Down
15 changes: 15 additions & 0 deletions notes.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ const char *notes_get_name(enum note_type note_type)
return note_templates[note_type].name;
}

bool note_has_field(enum note_type note_type, const char *field)
{
const char **p;
if (note_type <= NOTE_TYPE_NONE || note_type >= NUM_NOTE_TYPES)
return true;

p = note_templates[note_type].fields;
while (*p) {
if (!strcmp(field, *p))
return true;
p++;
}
return false;
}

enum note_type notes_get_type_by_shortname(const char *type_str)
{
BUILD_BUG_ON(ARRAY_SIZE(note_templates) != NUM_NOTE_TYPES);
Expand Down
3 changes: 3 additions & 0 deletions notes.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef NOTE_TYPES
#define NOTE_TYPES

#include <stdbool.h>

enum note_type {
NOTE_TYPE_NONE = -1,
NOTE_TYPE_AMEX,
Expand Down Expand Up @@ -34,6 +36,7 @@ struct note_template {
extern struct note_template note_templates[];

const char *notes_get_name(enum note_type note_type);
bool note_has_field(enum note_type note_type, const char *field);
enum note_type notes_get_type_by_shortname(const char *shortname);
enum note_type notes_get_type_by_name(const char *type_str);
char *note_type_usage();
Expand Down

0 comments on commit 1ae6957

Please sign in to comment.