lua/ldump.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 23 Jun 2017 17:28:03 -0400
changeset 58 1390348facc7
parent 0 d7ee4e2ed49d
permissions -rw-r--r--
Command line tool that decrypts an OPVault keychain and dumps it to stdout.

To compile: gcc -o opvault opvault.c cJSON.c -lcrypto

Usage: ./opvault </path/to/mykeychain.opvault> <password>

This is just a proof of concept; I'll be recycling this into proper OPVault
support in 1pass later and deleting this tool.

This uses OpenSSL's libcrypto for the math instead of all the homegrown
crypto this project is otherwise using. I'll probably migrate the rest in
this direction, too, since this wasn't as bad as I expected to use and
gets you all the package-manager mojo of automatic bug fixes and security
patches and shared code, etc.

cJSON parses JSON in C. That is from https://github.com/DaveGamble/cJSON

An example OPVault keychain from AgileBits is available here:

https://cache.agilebits.com/security-kb/
icculus@0
     1
/*
icculus@0
     2
** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $
icculus@0
     3
** save precompiled Lua chunks
icculus@0
     4
** See Copyright Notice in lua.h
icculus@0
     5
*/
icculus@0
     6
icculus@0
     7
#include <stddef.h>
icculus@0
     8
icculus@0
     9
#define ldump_c
icculus@0
    10
#define LUA_CORE
icculus@0
    11
icculus@0
    12
#include "lua.h"
icculus@0
    13
icculus@0
    14
#include "lobject.h"
icculus@0
    15
#include "lstate.h"
icculus@0
    16
#include "lundump.h"
icculus@0
    17
icculus@0
    18
typedef struct {
icculus@0
    19
 lua_State* L;
icculus@0
    20
 lua_Writer writer;
icculus@0
    21
 void* data;
icculus@0
    22
 int strip;
icculus@0
    23
 int status;
icculus@0
    24
} DumpState;
icculus@0
    25
icculus@0
    26
#define DumpMem(b,n,size,D)	DumpBlock(b,(n)*(size),D)
icculus@0
    27
#define DumpVar(x,D)		DumpMem(&x,1,sizeof(x),D)
icculus@0
    28
icculus@0
    29
static void DumpBlock(const void* b, size_t size, DumpState* D)
icculus@0
    30
{
icculus@0
    31
 if (D->status==0)
icculus@0
    32
 {
icculus@0
    33
  lua_unlock(D->L);
icculus@0
    34
  D->status=(*D->writer)(D->L,b,size,D->data);
icculus@0
    35
  lua_lock(D->L);
icculus@0
    36
 }
icculus@0
    37
}
icculus@0
    38
icculus@0
    39
static void DumpChar(int y, DumpState* D)
icculus@0
    40
{
icculus@0
    41
 char x=(char)y;
icculus@0
    42
 DumpVar(x,D);
icculus@0
    43
}
icculus@0
    44
icculus@0
    45
static void DumpInt(int x, DumpState* D)
icculus@0
    46
{
icculus@0
    47
 DumpVar(x,D);
icculus@0
    48
}
icculus@0
    49
icculus@0
    50
static void DumpNumber(lua_Number x, DumpState* D)
icculus@0
    51
{
icculus@0
    52
 DumpVar(x,D);
icculus@0
    53
}
icculus@0
    54
icculus@0
    55
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
icculus@0
    56
{
icculus@0
    57
 DumpInt(n,D);
icculus@0
    58
 DumpMem(b,n,size,D);
icculus@0
    59
}
icculus@0
    60
icculus@0
    61
static void DumpString(const TString* s, DumpState* D)
icculus@0
    62
{
icculus@0
    63
 if (s==NULL)
icculus@0
    64
 {
icculus@0
    65
  size_t size=0;
icculus@0
    66
  DumpVar(size,D);
icculus@0
    67
 }
icculus@0
    68
 else
icculus@0
    69
 {
icculus@0
    70
  size_t size=s->tsv.len+1;		/* include trailing '\0' */
icculus@0
    71
  DumpVar(size,D);
icculus@0
    72
  DumpBlock(getstr(s),size*sizeof(char),D);
icculus@0
    73
 }
icculus@0
    74
}
icculus@0
    75
icculus@0
    76
#define DumpCode(f,D)	 DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
icculus@0
    77
icculus@0
    78
static void DumpFunction(const Proto* f, DumpState* D);
icculus@0
    79
icculus@0
    80
static void DumpConstants(const Proto* f, DumpState* D)
icculus@0
    81
{
icculus@0
    82
 int i,n=f->sizek;
icculus@0
    83
 DumpInt(n,D);
icculus@0
    84
 for (i=0; i<n; i++)
icculus@0
    85
 {
icculus@0
    86
  const TValue* o=&f->k[i];
icculus@0
    87
  DumpChar(ttypenv(o),D);
icculus@0
    88
  switch (ttypenv(o))
icculus@0
    89
  {
icculus@0
    90
   case LUA_TNIL:
icculus@0
    91
	break;
icculus@0
    92
   case LUA_TBOOLEAN:
icculus@0
    93
	DumpChar(bvalue(o),D);
icculus@0
    94
	break;
icculus@0
    95
   case LUA_TNUMBER:
icculus@0
    96
	DumpNumber(nvalue(o),D);
icculus@0
    97
	break;
icculus@0
    98
   case LUA_TSTRING:
icculus@0
    99
	DumpString(rawtsvalue(o),D);
icculus@0
   100
	break;
icculus@0
   101
    default: lua_assert(0);
icculus@0
   102
  }
icculus@0
   103
 }
icculus@0
   104
 n=f->sizep;
icculus@0
   105
 DumpInt(n,D);
icculus@0
   106
 for (i=0; i<n; i++) DumpFunction(f->p[i],D);
icculus@0
   107
}
icculus@0
   108
icculus@0
   109
static void DumpUpvalues(const Proto* f, DumpState* D)
icculus@0
   110
{
icculus@0
   111
 int i,n=f->sizeupvalues;
icculus@0
   112
 DumpInt(n,D);
icculus@0
   113
 for (i=0; i<n; i++)
icculus@0
   114
 {
icculus@0
   115
  DumpChar(f->upvalues[i].instack,D);
icculus@0
   116
  DumpChar(f->upvalues[i].idx,D);
icculus@0
   117
 }
icculus@0
   118
}
icculus@0
   119
icculus@0
   120
static void DumpDebug(const Proto* f, DumpState* D)
icculus@0
   121
{
icculus@0
   122
 int i,n;
icculus@0
   123
 DumpString((D->strip) ? NULL : f->source,D);
icculus@0
   124
 n= (D->strip) ? 0 : f->sizelineinfo;
icculus@0
   125
 DumpVector(f->lineinfo,n,sizeof(int),D);
icculus@0
   126
 n= (D->strip) ? 0 : f->sizelocvars;
icculus@0
   127
 DumpInt(n,D);
icculus@0
   128
 for (i=0; i<n; i++)
icculus@0
   129
 {
icculus@0
   130
  DumpString(f->locvars[i].varname,D);
icculus@0
   131
  DumpInt(f->locvars[i].startpc,D);
icculus@0
   132
  DumpInt(f->locvars[i].endpc,D);
icculus@0
   133
 }
icculus@0
   134
 n= (D->strip) ? 0 : f->sizeupvalues;
icculus@0
   135
 DumpInt(n,D);
icculus@0
   136
 for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D);
icculus@0
   137
}
icculus@0
   138
icculus@0
   139
static void DumpFunction(const Proto* f, DumpState* D)
icculus@0
   140
{
icculus@0
   141
 DumpInt(f->linedefined,D);
icculus@0
   142
 DumpInt(f->lastlinedefined,D);
icculus@0
   143
 DumpChar(f->numparams,D);
icculus@0
   144
 DumpChar(f->is_vararg,D);
icculus@0
   145
 DumpChar(f->maxstacksize,D);
icculus@0
   146
 DumpCode(f,D);
icculus@0
   147
 DumpConstants(f,D);
icculus@0
   148
 DumpUpvalues(f,D);
icculus@0
   149
 DumpDebug(f,D);
icculus@0
   150
}
icculus@0
   151
icculus@0
   152
static void DumpHeader(DumpState* D)
icculus@0
   153
{
icculus@0
   154
 lu_byte h[LUAC_HEADERSIZE];
icculus@0
   155
 luaU_header(h);
icculus@0
   156
 DumpBlock(h,LUAC_HEADERSIZE,D);
icculus@0
   157
}
icculus@0
   158
icculus@0
   159
/*
icculus@0
   160
** dump Lua function as precompiled chunk
icculus@0
   161
*/
icculus@0
   162
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
icculus@0
   163
{
icculus@0
   164
 DumpState D;
icculus@0
   165
 D.L=L;
icculus@0
   166
 D.writer=w;
icculus@0
   167
 D.data=data;
icculus@0
   168
 D.strip=strip;
icculus@0
   169
 D.status=0;
icculus@0
   170
 DumpHeader(&D);
icculus@0
   171
 DumpFunction(f,&D);
icculus@0
   172
 return D.status;
icculus@0
   173
}