diff --git a/src/commands.h b/src/commands.h new file mode 100644 index 0000000..fdcaf79 --- /dev/null +++ b/src/commands.h @@ -0,0 +1,30 @@ +#ifndef __COMMANDS_H__ +#define __COMMANDS_H__ +/* +moolticute-pass + +Copyright (C) 2018 Dominik Meyer + +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 3 of the License, 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, see . +*/ + +/** +* @file commands.h +* @brief header file for moolticute-pass commands +* @author Dominik Meyer +* @copyright 2018 by Dominik Meyer +*/ + +int get(int argc, char **argv); ///< get the password from the mooltipass device +#endif diff --git a/src/get.c b/src/get.c new file mode 100644 index 0000000..66e8500 --- /dev/null +++ b/src/get.c @@ -0,0 +1,167 @@ +/* +moolticute-pass + +Copyright (C) 2018 Dominik Meyer + +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 3 of the License, 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, see . +*/ + +/** +* @file get.c +* @brief source file for the get command +* @author Dominik Meyer +* @copyright 2018 by Dominik Meyer +*/ +#include "../libmoolticute-c/src/moolticute.h" +#include "../yaap/src/argparse.h" +#include "x11_clipboard.h" +#include "../config.h" + +/** +* @brief get the password of a services and login +* +* @param argc - number of command line arguments +* @param argv - array of command line arguments +* +* @return standard return value +*/ +int get(int argc, char **argv) +{ + struct arg_parse_ctx *argparse_ctx = argparse_init(); + struct moolticute_ctx *ctx; + int ret=0; + char password[500]; + char service[250]; + char user[250]; + + struct arg_str str1 = { + {0,1,0}, + 's', + "service", + service, + 250, + "service name of the requested password" + }; + argparse_add_string(argparse_ctx, &str1); + + struct arg_str str2 = { + {0,1,0}, + 'u', + "user", + user, + 250, + "user name for the requested password" + }; + argparse_add_string(argparse_ctx, &str2); + + +/** +* if X11 clipboard is enabled add argument for selecting it +*/ +#ifdef HAVE_X11 + struct arg_flag x11 = { + {ARG_FLAG,0,0}, + 'c', + "clipboard", + "copy password to X11 clipboard instead stdout", + NULL + }; + argparse_add_flag(argparse_ctx, &x11); +#endif + + ret=argparse_parse(argparse_ctx, argc, argv); + + if (ret < 0 ) + { + return -1; + } + +/** +* if X11 clipboard is enabled check if is selected and init x11 context +*/ +#ifdef HAVE_X11 +struct x11_ctx *x11ctx; + +if (x11.base.set == 1) +{ + // x11 is selected + x11ctx = x11_init(); +} +#endif + + // create moolticute context + ctx=moolticute_init_ctx(); + if (ctx == NULL) + { + fprintf(stderr,"ERROR: can not create library context.\n"); + return -1; + } + + // connect to moolticute daemon + ret=moolticute_connect(ctx); + if (ret < 0) + { + fprintf(stderr,"ERROR: can not connect to moolticute daemon. Is daemon running and is environment variable correctly set?\n"); + return -1; + } + + ret=moolticute_request_password(ctx, service, user, password,30); + if (ret < 0) + { + if (ret == M_ERROR_TIMEOUT) + { + fprintf(stderr,"ERROR: Timeout waiting for data. You have to acknowledge credential management on your device\n"); + return -1; + } + + if (ret == M_ERROR_NO_CARD) + { + fprintf(stderr,"ERROR: No cryptocard in device. Please insert your card\n"); + return -1; + } + + if (ret == M_ERROR_NO_MOOLTIPASS_DEVICE) + { + fprintf(stderr,"ERROR: No mooltipass device is connected to moolticute daemon. Please connect your device\n"); + return -1; + } + + if (ret == M_ERROR_DEVICE_LOCKED) + { + fprintf(stderr,"ERROR: Mooltipass device is locked. Please unlock it.\n"); + return -1; + } + + if (ret == M_ERROR_APPROVAL_REQUIRED) + { + fprintf(stderr,"ERROR: Please approve action on mooltipass device.\n"); + return -1; + } + + return -1; + } + +#ifdef HAVE_X11 + if (x11.base.set == 1) + { + x11_put_clipboard(x11ctx, password); + return 0; + } +#endif + + printf("%s", password); + + + return 0; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..943ab34 --- /dev/null +++ b/src/main.c @@ -0,0 +1,61 @@ +/* +moolticute-pass + +Copyright (C) 2018 Dominik Meyer + +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 3 of the License, 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, see . +*/ + +/** +* @file main.c +* @brief Main C Source file for the moolticute-pass application +* @author Dominik Meyer +* @copyright 2018 by Dominik Meyer +*/ +#include +#include +#include "commands.h" +#include "../yaap/src/argparse.h" + +/** +* @brief main function of the moolticute-pass application +* +* @param argc - number of command line arguments +* @param argv - array of command line arguments +* +* @return standard return value +*/ +int main(int argc, char **argv) +{ + // initialize argument parser context + struct arg_parse_ctx *argparse_ctx = argparse_init(); + + // command-line get command + struct arg_parse_cmd get_cmd = { + {ARG_CMD,1,0}, // set it mandatory, all commands should be mandatory + 0, + "get", + "get a password from mooltipass device", + &get + }; + argparse_add_command(argparse_ctx, &get_cmd); + + // parse the command line, this function calls the correct function for each command + int ret=argparse_parse(argparse_ctx, argc, argv); + + // free the argument parser context + argparse_free(argparse_ctx); + + return ret; +} diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c new file mode 100644 index 0000000..89c132c --- /dev/null +++ b/src/x11_clipboard.c @@ -0,0 +1,189 @@ +/* +moolticute-pass + +Copyright (C) 2018 Dominik Meyer + +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 3 of the License, 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, see . +*/ + +/** +* @file x11_clipboard.c +* @brief source file for all x11 functions +* @author Dominik Meyer +* @copyright 2018 by Dominik Meyer +*/ +#include "x11_clipboard.h" +#include +#include +#include +#include + + +/** +* @brief initialize the x11 context +* +* @return an initialized x11_ctx structure +*/ +struct x11_ctx *x11_init() +{ + struct x11_ctx *ctx = (struct x11_ctx *) calloc(sizeof(struct x11_ctx), 1); + + // open the X11 display + ctx->dpy = XOpenDisplay(NULL); + if (!ctx->dpy) + { + fprintf(stderr, "Could not open X display\n"); + return NULL; + } + + ctx->screen = DefaultScreen(ctx->dpy); + ctx->root = RootWindow(ctx->dpy, ctx->screen); + + /* We need a window to receive messages from other clients. */ + ctx->owner = XCreateSimpleWindow(ctx->dpy, ctx->root, -10, -10, 1, 1, 0, 0, 0); + XSelectInput(ctx->dpy, ctx->owner, SelectionClear | SelectionRequest); + + ctx->sel = XInternAtom(ctx->dpy, "CLIPBOARD", False); + ctx->utf8 = XInternAtom(ctx->dpy, "UTF8_STRING", False); + + XMapWindow(ctx->dpy, ctx->owner); + XFlush(ctx->dpy); + + ctx->timeout = X11_DEFAULT_TIMEOUT; + + return ctx; +} + +/** +* @brief deny a clipboard request +* +* @param ctx - the x11 context +*/ +void send_no(struct x11_ctx *ctx) +{ + XSelectionEvent ssev; + char *an; + + if (ctx == NULL) + { + return; + } + + + an = XGetAtomName(ctx->dpy, ctx->sev->target); + if (an) + XFree(an); + + /* All of these should match the values of the request. */ + ssev.type = SelectionNotify; + ssev.requestor = ctx->sev->requestor; + ssev.selection = ctx->sev->selection; + ssev.target = ctx->sev->target; + ssev.property = None; /* signifies "nope" */ + ssev.time = ctx->sev->time; + + XSendEvent(ctx->dpy, ctx->sev->requestor, True, NoEventMask, (XEvent *)&ssev); +} + +/** +* @brief send an utf8 string on a clipboard request +* +* @param ctx - the x11 context +* @param text - text to send on clipboard request +*/ +void send_utf8(struct x11_ctx *ctx, char *text) +{ + XSelectionEvent ssev; + char *an; + + an = XGetAtomName(ctx->dpy, ctx->sev->property); + printf("Sending data to window 0x%lx, property '%s'\n", ctx->sev->requestor, an); + if (an) + XFree(an); + + XChangeProperty(ctx->dpy, ctx->sev->requestor, ctx->sev->property, ctx->utf8, 8, PropModeReplace, + (const unsigned char*) text, strlen(text)); + + ssev.type = SelectionNotify; + ssev.requestor = ctx->sev->requestor; + ssev.selection = ctx->sev->selection; + ssev.target = ctx->sev->target; + ssev.property = ctx->sev->property; + ssev.time = ctx->sev->time; + + XSendEvent(ctx->dpy, ctx->sev->requestor, True, NoEventMask, (XEvent *)&ssev); +} + + +/** +* @brief request the clipboard and wait for requests +* +* @param ctx - x11 context +* @param text - the text to copy to clipboard +* +* @return 0 - everything is fine +* @return <0 - error occured +*/ +int x11_put_clipboard(struct x11_ctx *ctx, char *text) +{ + int x11_fd; + fd_set in_fds; + struct timeval tv; + + if (ctx == NULL || text == NULL ) + { + return -1; + } + + XSetSelectionOwner(ctx->dpy, ctx->sel, ctx->owner, CurrentTime); + x11_fd = ConnectionNumber(ctx->dpy); + + while(1) + { + FD_ZERO(&in_fds); + FD_SET(x11_fd, &in_fds); + + // Set our timer. One second sounds good. + tv.tv_usec = 0; + tv.tv_sec = 20; + // Wait for sX Event or a Timer + if (select(x11_fd+1, &in_fds, 0, 0, &tv)) + { + while(XPending(ctx->dpy)) + { + XNextEvent(ctx->dpy, &ctx->ev); + switch (ctx->ev.type) + { + case SelectionClear: + return 1; + break; + case SelectionRequest: + ctx->sev = (XSelectionRequestEvent*)&ctx->ev.xselectionrequest; + /* Property is set to None by "obsolete" clients. */ + if (ctx->sev->target != ctx->utf8 || ctx->sev->property == None) + send_no(ctx); + else + send_utf8(ctx, text); + break; + } + } + } + else + { + break; + } + + } + return 0; +} diff --git a/src/x11_clipboard.h b/src/x11_clipboard.h new file mode 100644 index 0000000..a749e5f --- /dev/null +++ b/src/x11_clipboard.h @@ -0,0 +1,53 @@ +#ifndef __X11_CLIPBOARD_H__ +#define __X11_CLIPBOARD_H__ +/* +moolticute-pass + +Copyright (C) 2018 Dominik Meyer + +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 3 of the License, 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, see . +*/ + +/** +* @file x11_clipboard.h +* @brief header file for X11 specific structures and functions +* @author Dominik Meyer +* @copyright 2018 by Dominik Meyer +*/ +#include + + +#define X11_DEFAULT_TIMEOUT 10 ///< default timeout for copying anything to the clipboard + +/** +* @brief structure representing the X11 context +*/ +struct x11_ctx { + Display *dpy; ///< X11 Display + Window owner; ///< created window + Window root; ///< root window + int screen; ///< the screen + Atom sel; ///< a selection + Atom utf8; ///< utf atom + XEvent ev; ///< an event + XSelectionRequestEvent *sev; ///< selection request event + int timeout; ///< timeout after which to clear clipboard +}; + + + +struct x11_ctx *x11_init(); ///< initialize the x11 context +int x11_put_clipboard(struct x11_ctx *ctx, char *text); ///< put text into the clipboard + +#endif