예제 #1
0
파일: aqwin.c 프로젝트: droyo/graphics
Aqwin *aqwin_open(const char *cfg) {
	Aqwin *win;
	aqwin_param *p;
	
	if ((p = parse_cfg(cfg)) == NULL) {
		complain("aqwin_open: invalid config \"%s\"\n", cfg);
		return NULL;
	}
	print_params(p);
	win = aqwin_create(p);
	aqwin_param_free(p);
	return win;
}
예제 #2
0
파일: cfg_ini.c 프로젝트: Jmurdock13/libzt
zt_cfg_ty *
zt_cfg_ini(char *file, int opts )
{
    zt_cfg_ty *cfg = zt_cfg_new(&vtbl);

    cfg->filename = strdup(file);
    cfg->opts = opts;
    if (parse_cfg(cfg) < 0) {
        free(cfg->filename);
        free(cfg);
        cfg = NULL;
    }

    return cfg;
}
예제 #3
0
int main (int argc, char *argv[])
{
	int	count = 0;
	arc_t	*arc;

	if (argc < 2) {
		printf ("Usage: %s cfgfile\n\n", argv[0]);
		exit (1);
	}

	arc = arc_new (outfile, (arc_sig_t *)signature);
	if (arc == NULL) {
		printf ("*** Error: failed to create empty archive!\n");
		exit (42);
	}

	count = parse_cfg (argv[1], arc);
	printf ("Config file \"%s\" contains %d items.\n", argv[1], count);

	arc_store (arc);

	return (0);
}
예제 #4
0
int32_t main(int argc, char *argv[])
{
	int32_t opt;
	uint32_t n;
	char *cfgfile = NULL;
	struct stat sb;
	struct bitcoind *b, *sigfrom;
	struct psj *psj;
	struct sigaction act;
	struct config *cfg;

	cfg = malloc(sizeof(*cfg));
	if (cfg == NULL)
	{
		APPLOG(LOG_CRIT, "cfg malloc failed");
		exit(255);
	}

	while ((opt = getopt(argc, argv, "hs:c:")) != -1)
	{
		switch(opt)
		{
			case 'c':
				cfgfile = optarg;
				break;
			case 's':
				cfg->force_pid = atoi(optarg);
				break;

			default:
			case 'h':
				usage();
		}
	}

	APPLOG(LOG_NOTICE, "psj_sigmon v0.5 starting up");

	/* config file parsing */
	if (parse_cfg(cfgfile ? cfgfile : "config.cfg", cfg))
	{
		APPLOG(LOG_CRIT, "parse_cfg error");
		exit(255);
	}

	if (cfg->bitcoind_used == 0)
	{
		APPLOG(LOG_CRIT, "no bitcoind defined, exiting");
		exit(EXIT_SUCCESS);
	}
	if (cfg->psj_used == 0)
	{
		APPLOG(LOG_CRIT, "no psj defined, exiting");
		exit(EXIT_SUCCESS);
	}

	if (cfg->pidfile)
	{
		if (write_pidfile(cfg->pidfile) != 0)
		{
			APPLOG(LOG_CRIT, "write_pidfile failed");
			exit(255);
		}
	}

	if (cfg->daemon)
	{
		APPLOG(LOG_NOTICE, "daemonising, you will hear no more from me");
		if (daemon(false, false) == -1)
		{
			APPLOG(LOG_CRIT, "except daemonising failed..  dying");
			exit(255);
		}
		cfg->daemon_done = true;
	}

	/* install signal handlers */
	act.sa_flags = SA_SIGINFO;
	act.sa_sigaction = &sig_handler;
	sigaction(SIGUSR1, &act, NULL);
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);


	while(1)
	{
		select(0, NULL, NULL, NULL, NULL);

		APPLOG(LOG_INFO, "got signal %d, from pid %d", sig, pid);

		/* handle INT and TERM */
		if (sig == SIGINT || sig == SIGTERM)
			/* break out of loop and exit gracefully */
			break;

		/* ignore non-USR1 */
		if (sig != SIGUSR1)
			continue;

		if (cfg->force_pid)
		{
			pid = cfg->force_pid;
			APPLOG(LOG_DEBUG, "forcing sending-pid to %d", pid);
		}

		sigfrom = NULL;
		for(n = 0 ; n < cfg->bitcoind_used ; n++)
		{
			/* check if pid == this bitcoind's pid */
			b = cfg->bitcoind_list[n];
			
			if (stat(b->pidfile, &sb) == -1)
			{
				APPLOG(LOG_WARNING, "%s on stat of %s", strerror(errno), b->pidfile);
				continue;
			}

			if (sb.st_mtime > b->pidfile_mtime)
			{
				/* refresh what we think the pid is of this
				 * bitcoind */
				b->pid = read_pidfile(b->pidfile);
				b->pidfile_mtime = sb.st_mtime;
				APPLOG(LOG_DEBUG, "%s changed: new pid is %u", b->pidfile, b->pid);
			}

			if (b->pid == pid)
			{
				APPLOG(LOG_DEBUG, "signal matches %s (%s)", b->pidfile, b->name);
				sigfrom = b;
				break;
			}
		}

		if (sigfrom == NULL)
		{
			APPLOG(LOG_WARNING, "signal not from a recognised pid");
			continue;
		}

		/* tell each psj about b->name */
		for(n = 0 ; n < cfg->psj_used ; n++)
		{
			psj = cfg->psj_list[n];
			APPLOG(LOG_INFO, "notifying %s of signal", psj->hostport);
			poke_psj(cfg,psj, b);
		}
	}

	APPLOG(LOG_INFO, "shutting down, removing pidfile");
	unlink(cfg->pidfile);

	/* we're lazy, the kernel will clean up our memory, sorry valgrind :p */

	return EXIT_SUCCESS;
}
예제 #5
0
PAM_EXTERN int
pam_sm_authenticate (pam_handle_t * pamh,
                     int flags, int argc, const char **argv)
{
    int retval, rc;
    const char *user = NULL;
    const char *password = NULL;
    char otp[MAX_TOKEN_ID_LEN + TOKEN_OTP_LEN + 1] = { 0 };
    char otp_id[MAX_TOKEN_ID_LEN + 1] = { 0 };
    int password_len = 0;
    int skip_bytes = 0;
    int valid_token = 0;
    struct pam_conv *conv;
    struct pam_message *pmsg[1], msg[1];
    struct pam_response *resp;
    int nargs = 1;
    ykclient_t *ykc = NULL;
    struct cfg cfg_st;
    struct cfg *cfg = &cfg_st; /* for DBG macro */

    parse_cfg (flags, argc, argv, cfg);

    retval = pam_get_user (pamh, &user, NULL);
    if (retval != PAM_SUCCESS)
    {
        DBG (("get user returned error: %s", pam_strerror (pamh, retval)));
        goto done;
    }
    DBG (("get user returned: %s", user));

    if (cfg->mode == CHRESP) {
#if HAVE_LIBYKPERS_1
        return do_challenge_response(pamh, cfg, user);
#else
        DBG (("no support for challenge/response"));
        retval = PAM_AUTH_ERR;
        goto done;
#endif
    }

    if (cfg->try_first_pass || cfg->use_first_pass)
    {
        retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password);
        if (retval != PAM_SUCCESS)
        {
            DBG (("get password returned error: %s",
                  pam_strerror (pamh, retval)));
            goto done;
        }
        DBG (("get password returned: %s", password));
    }

    if (cfg->use_first_pass && password == NULL)
    {
        DBG (("use_first_pass set and no password, giving up"));
        retval = PAM_AUTH_ERR;
        goto done;
    }

    rc = ykclient_init (&ykc);
    if (rc != YKCLIENT_OK)
    {
        DBG (("ykclient_init() failed (%d): %s", rc, ykclient_strerror (rc)));
        retval = PAM_AUTHINFO_UNAVAIL;
        goto done;
    }

    rc = ykclient_set_client_b64 (ykc, cfg->client_id, cfg->client_key);
    if (rc != YKCLIENT_OK)
    {
        DBG (("ykclient_set_client_b64() failed (%d): %s",
              rc, ykclient_strerror (rc)));
        retval = PAM_AUTHINFO_UNAVAIL;
        goto done;
    }

    if (cfg->capath)
        ykclient_set_ca_path (ykc, cfg->capath);

    if (cfg->url)
        ykclient_set_url_template (ykc, cfg->url);

    if (password == NULL)
    {
        retval = pam_get_item (pamh, PAM_CONV, (const void **) &conv);
        if (retval != PAM_SUCCESS)
        {
            DBG (("get conv returned error: %s", pam_strerror (pamh, retval)));
            goto done;
        }

        pmsg[0] = &msg[0];
        {
            const char *query_template = "Yubikey for `%s': ";
            size_t len = strlen (query_template) + strlen (user);
            size_t wrote;

            msg[0].msg = malloc (len);
            if (!msg[0].msg)
            {
                retval = PAM_BUF_ERR;
                goto done;
            }

            wrote = snprintf ((char *) msg[0].msg, len, query_template, user);
            if (wrote < 0 || wrote >= len)
            {
                retval = PAM_BUF_ERR;
                goto done;
            }
        }
        msg[0].msg_style = cfg->verbose_otp ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
        resp = NULL;

        retval = conv->conv (nargs, (const struct pam_message **) pmsg,
                             &resp, conv->appdata_ptr);

        free ((char *) msg[0].msg);

        if (retval != PAM_SUCCESS)
        {
            DBG (("conv returned error: %s", pam_strerror (pamh, retval)));
            goto done;
        }

        if (resp->resp == NULL)
        {
            DBG (("conv returned NULL passwd?"));
            goto done;
        }

        DBG (("conv returned %i bytes", strlen(resp->resp)));

        password = resp->resp;
    }

    password_len = strlen (password);
    if (password_len < (cfg->token_id_length + TOKEN_OTP_LEN))
    {
        DBG (("OTP too short to be considered : %i < %i", password_len, (cfg->token_id_length + TOKEN_OTP_LEN)));
        retval = PAM_AUTH_ERR;
        goto done;
    }

    /* In case the input was systempassword+YubiKeyOTP, we want to skip over
       "systempassword" when copying the token_id and OTP to separate buffers */
    skip_bytes = password_len - (cfg->token_id_length + TOKEN_OTP_LEN);

    DBG (("Skipping first %i bytes. Length is %i, token_id set to %i and token OTP always %i.",
          skip_bytes, password_len, cfg->token_id_length, TOKEN_OTP_LEN));

    /* Copy full YubiKey output (public ID + OTP) into otp */
    strncpy (otp, password + skip_bytes, sizeof (otp) - 1);
    /* Copy only public ID into otp_id. Destination buffer is zeroed. */
    strncpy (otp_id, password + skip_bytes, cfg->token_id_length);

    DBG (("OTP: %s ID: %s ", otp, otp_id));

    /* user entered their system password followed by generated OTP? */
    if (password_len > TOKEN_OTP_LEN + cfg->token_id_length)
    {
        char *onlypasswd = strdup (password);

        onlypasswd[password_len - (TOKEN_OTP_LEN + cfg->token_id_length)] = '\0';

        DBG (("Extracted a probable system password entered before the OTP - "
              "setting item PAM_AUTHTOK"));

        retval = pam_set_item (pamh, PAM_AUTHTOK, onlypasswd);
        free (onlypasswd);
        if (retval != PAM_SUCCESS)
        {
            DBG (("set_item returned error: %s", pam_strerror (pamh, retval)));
            goto done;
        }
    }
    else
        password = NULL;

    rc = ykclient_request (ykc, otp);

    DBG (("ykclient return value (%d): %s", rc,
          ykclient_strerror (rc)));

    switch (rc)
    {
    case YKCLIENT_OK:
        break;

    case YKCLIENT_BAD_OTP:
    case YKCLIENT_REPLAYED_OTP:
        retval = PAM_AUTH_ERR;
        goto done;

    default:
        retval = PAM_AUTHINFO_UNAVAIL;
        goto done;
    }

    /* authorize the user with supplied token id */
    if (cfg->ldapserver != NULL || cfg->ldap_uri != NULL)
        valid_token = authorize_user_token_ldap (cfg, user, otp_id);
    else
        valid_token = authorize_user_token (cfg, user, otp_id);

    if (valid_token == 0)
    {
        DBG (("Yubikey not authorized to login as user"));
        retval = PAM_AUTHINFO_UNAVAIL;
        goto done;
    }

    retval = PAM_SUCCESS;

done:
    if (ykc)
        ykclient_done (&ykc);
    if (cfg->alwaysok && retval != PAM_SUCCESS)
    {
        DBG (("alwaysok needed (otherwise return with %d)", retval));
        retval = PAM_SUCCESS;
    }
    DBG (("done. [%s]", pam_strerror (pamh, retval)));
    pam_set_data (pamh, "yubico_setcred_return", (void*) (intptr_t) retval, NULL);

    return retval;
}
예제 #6
0
파일: canvas.hpp 프로젝트: ArtBears/wesnoth
	/**
	 * Sets the config.
	 *
	 * @param cfg                 The config object with the data to draw, see
	 *                            http://www.wesnoth.org/wiki/GUICanvasWML for
	 *                            more information.
	 */
	void set_cfg(const config& cfg)
	{
		parse_cfg(cfg);
	}
int main (int argc, char ** argv)
{
	struct dirent ** plugin_list;
	unsigned int i;
	int plugin_count;
	char * plugin_dir = NULL;
	char * basename = NULL;

	if (argc == 1)
	{
		usage(argv[0]);
		return EXIT_FAILURE;
	}

	for (i = 1; i < argc; i++)
	{
		if (!strcmp(argv[i], "-l"))
		{
			if (argc > i + 1)
			{
				plugin_dir = (char *) malloc(strlen(argv[i + 1]) + 1);
				strcpy(plugin_dir, argv[i + 1]);
				i++;
			}
		}
		else if (!strcmp(argv[i], "-x"))
		{
			if (argc > i + 1)
			{
				basename = (char *) malloc(strlen(argv[i + 1]) + 1);
				strcpy(basename, argv[i + 1]);
				i++;
			}
			else
			{
				usage(argv[0]);
				free(plugin_dir);
				return EXIT_FAILURE;
			}
		}
		else
		{
			usage(argv[0]);
			free(basename);
			free(plugin_dir);
			return EXIT_FAILURE;
		}
	}

	if (plugin_dir == NULL)
	{
		plugin_dir = (char *) malloc(strlen(PLUGINDIR) + 1);
		strcpy(plugin_dir, PLUGINDIR);
	}

	if (!basename)
	{
		plugin_count = scandir(plugin_dir, &plugin_list, 0, alphasort);

		if (plugin_count < 0)
		{
			perror("scandir");
			free(plugin_dir);
			return EXIT_FAILURE;
		}

		for (i = 0; i < plugin_count; i++)
		{
			if (fnmatch("*.cfg", plugin_list[i]->d_name, 0) == 0)
			{
				plugin_list[i]->d_name[strlen(plugin_list[i]->d_name) - 4] = 0;
				printf("%s\n", plugin_list[i]->d_name);
			}

			free(plugin_list[i]);
		}

		free(plugin_list);
	}
	else
	{
		char plugin_path[strlen(plugin_dir) + strlen(basename) + 5];
		struct stat plugin_stat;

		sprintf(plugin_path, "%s/%s.cfg", plugin_dir, basename);

		if (stat(plugin_path, &plugin_stat) == -1)
		{
			perror("stat");
		}
		else
		{
			PluginParam * plugin_param = parse_cfg(plugin_path);

			if (plugin_param == NULL)
			{
				printf("error parsing %s\n", plugin_path);
			}
			else
			{
				sprintf(plugin_path, "%s/%s.so", plugin_dir, basename);

				if (stat(plugin_path, &plugin_stat) == -1)
				{
					perror("stat");
				}
				else
				{
					void * plugin_handle = dlopen(plugin_path, RTLD_NOW);

					if (plugin_handle == NULL)
					{
						printf("%s\n", dlerror());
					}
					else
					{
						PluginExec plugin_exec = (PluginExec) dlsym(plugin_handle, "plugin_exec");

						if (plugin_exec == NULL)
						{
							printf("%s\n", dlerror());
						}
						else
						{
							PluginParam * next = plugin_param->next;
							
							plugin_exec(plugin_param);

							while (plugin_param != NULL)
							{
								free(plugin_param->val);
								free(plugin_param);

								if (next)
								{
									plugin_param = next;
									next = plugin_param->next;
								}
								else
								{
									plugin_param = NULL;
								}
							}

							dlclose(plugin_handle);

							if (fb != -1)
							{
								ioctl(fb, AVIA_GT_GV_HIDE);
								close(fb);
							}

							if (rc != -1)
							{
								close(rc);
							}

							if (lcd != -1)
							{
								close(lcd);
							}
						}
					}
				}
			}
		}
		
		free(basename);
	}
	
	free(plugin_dir);

	if (handles != NULL)
	{
		struct handles_s * cur = handles->first;
		struct handles_s * next = handles->first->next;

		while (cur != NULL)
		{
			printf("unloading %s\n", cur->path);
			dlclose(cur->handle);
		
			free(cur->path);
			free(cur);

			if (next != NULL)
			{
				cur = next;
				next = cur->next;
			}
			else
			{
				cur = NULL;
			}
		}
	}

	return EXIT_SUCCESS;
}
예제 #8
0
Postagger::Postagger(ltp::utility::ConfigParser & cfg) :
    model(0), 
    decoder(0) {
    parse_cfg(cfg);
}
예제 #9
0
PAM_EXTERN int
pam_sm_authenticate (pam_handle_t * pamh,
		int flags, int argc, const char **argv)
{
	int retval, rc;
	dynalogin_client_t *session;
	const char *user = NULL;
	const char *password = NULL;
	char otp[MAX_OTP_LEN + 1];
	int password_len = 0;
	struct pam_conv *conv;
	struct pam_message *pmsg[1], msg[1];
	struct pam_response *resp;
	int nargs = 1;
	struct cfg cfg;
	char *query_prompt = NULL;
	char *onlypasswd = strdup ("");	/* empty passwords never match */

	parse_cfg (flags, argc, argv, &cfg);

	retval = pam_get_user (pamh, &user, NULL);
	if (retval != PAM_SUCCESS)
	{
		DBG (("get user returned error: %s", pam_strerror (pamh, retval)));
		goto done;
	}
	DBG (("get user returned: %s", user));

	if (cfg.try_first_pass || cfg.use_first_pass)
	{
		retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password);
		if (retval != PAM_SUCCESS)
		{
			DBG (("get password returned error: %s",
					pam_strerror (pamh, retval)));
			goto done;
		}
		DBG (("get password returned: %s", password));
	}

	if (cfg.use_first_pass && password == NULL)
	{
		DBG (("use_first_pass set and no password, giving up"));
		retval = PAM_AUTH_ERR;
		goto done;
	}

	session = dynalogin_session_start(cfg.server, cfg.port, cfg.ca_file);
	if (session == NULL)
	{
		DBG (("dynalogin_session_start() failed"));
		retval = PAM_AUTHINFO_UNAVAIL;
		goto done;
	}

	if (password == NULL)
	{
		retval = pam_get_item (pamh, PAM_CONV, (const void **) &conv);
		if (retval != PAM_SUCCESS)
		{
			DBG (("get conv returned error: %s", pam_strerror (pamh, retval)));
			goto done;
		}

		pmsg[0] = &msg[0];
		{
			const char *query_template = "One-time password (OATH) for `%s': ";
			size_t len = strlen (query_template) + strlen (user);
			size_t wrote;

			query_prompt = malloc (len);
			if (!query_prompt)
			{
				retval = PAM_BUF_ERR;
				goto done;
			}

			wrote = snprintf (query_prompt, len, query_template, user);
			if (wrote < 0 || wrote >= len)
			{
				retval = PAM_BUF_ERR;
				goto done;
			}

			msg[0].msg = query_prompt;
		}
		msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
		resp = NULL;

		retval = conv->conv (nargs, (const struct pam_message **) pmsg,
				&resp, conv->appdata_ptr);

		free (query_prompt);
		query_prompt = NULL;

		if (retval != PAM_SUCCESS)
		{
			DBG (("conv returned error: %s", pam_strerror (pamh, retval)));
			goto done;
		}

		DBG (("conv returned: %s", resp->resp));

		password = resp->resp;
	}

	if (password)
		password_len = strlen (password);
	else
	{
		DBG (("Could not read password"));
		retval = PAM_AUTH_ERR;
		goto done;
	}

	if (password_len < MIN_OTP_LEN)
	{
		DBG (("OTP too short: %s", password));
		retval = PAM_AUTH_ERR;
		goto done;
	}
	else if (password_len > MAX_OTP_LEN)
	{
		DBG (("OTP too long: %s", password));
		retval = PAM_AUTH_ERR;
		goto done;
	}
	else
	{
		strcpy (otp, password);
		password = NULL;
	}

	DBG (("OTP: %s", otp ? otp : "(null)"));

	{
		time_t last_otp;

		rc = dynalogin_session_authenticate(
				session, user, cfg.scheme, otp);
		DBG (("authenticate rc %d", rc));
	}

	if (rc != 0)
	{
		DBG (("One-time password not authorized to login as user '%s'", user));
		retval = PAM_AUTH_ERR;
		goto done;
	}

	retval = PAM_SUCCESS;

	done:
	dynalogin_session_stop(session);
	free (query_prompt);
	free (onlypasswd);
	if (cfg.alwaysok && retval != PAM_SUCCESS)
	{
		DBG (("alwaysok needed (otherwise return with %d)", retval));
		retval = PAM_SUCCESS;
	}
	DBG (("done. [%s]", pam_strerror (pamh, retval)));

	return retval;
}
예제 #10
0
static int fbsplash_load() {
	fb_fd = -1;
	last_pos = 0;

	/* Kick start our TTF library */
	if (TTF_Init() < 0) {
		printk("Couldn't initialise TTF.\n");
	}

	/* Find out the FB size */
	if (get_fb_settings(0)) {
		printk("Couldn't get fb settings.\n");
		return 1;
	}

	arg_vc = get_active_vt();
	arg_mode = 's';

	/* Read theme config file */
	if (arg_theme == NULL)
		arg_theme = DEFAULT_THEME;
	config_file = get_cfg_file(arg_theme);
	if (!config_file) {
		printk("Couldn't load config file %s.\n", arg_theme);
		return 1;
	} else
		printk("Using configuration file %s.\n", config_file);

	parse_cfg(config_file);

	/* Prime the font cache with glyphs so we don't need to allocate them later */
	TTF_PrimeCache("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -.", global_font, TTF_STYLE_NORMAL);

	boot_message = rendermessage;

	fb_fd = open_fb();
	if (fb_fd == -1) {
		printk("Couldn't open framebuffer device.\n");
		return 1;
	}

	if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR)
		set_directcolor_cmap(fb_fd);

	fbsplash_fd = open(SPLASH_DEV, O_WRONLY); /* Don't worry if it fails */

	do_getpic(FB_SPLASH_IO_ORIG_USER, 1, 'v'); /* Don't worry if it fails */
	if (do_getpic(FB_SPLASH_IO_ORIG_USER, 0, 's') == -1)
		no_silent_image = 1; /* We do care if this fails. */

	/* These next two touch the kernel and are needed even for silent mode, to
	 * get the colours right (even on 32-bit depth displays funnily enough. */
	do_config(FB_SPLASH_IO_ORIG_USER);
	cmd_setstate(1, FB_SPLASH_IO_ORIG_USER);

	/* copy the silent pic to base_image for safe keeping */
	if (!no_silent_image) {
		base_image_size = silent_img.width * silent_img.height * (silent_img.depth >> 3);
		base_image = malloc(base_image_size);
		if (!base_image) {
			printk("Couldn't get enough memory for framebuffer image.\n");
			return 1;
		}
		memcpy(base_image, (void*)silent_img.data, base_image_size);
	}
예제 #11
0
PAM_EXTERN int
pam_sm_authenticate (pam_handle_t * pamh,
		     int flags, int argc, const char **argv)
{
  int retval, rc;
  const char *user = NULL;
  const char *password = NULL;
  char otp[MAX_OTP_LEN + 1];
  int password_len = 0;
  struct pam_conv *conv;
  struct pam_message *pmsg[1], msg[1];
  struct pam_response *resp;
  int nargs = 1;
  struct cfg cfg;
  char *query_prompt = NULL;
  char *onlypasswd = strdup ("");	/* empty passwords never match */

  parse_cfg (flags, argc, argv, &cfg);

  retval = pam_get_user (pamh, &user, NULL);
  if (retval != PAM_SUCCESS)
    {
      DBG (("get user returned error: %s", pam_strerror (pamh, retval)));
      goto done;
    }
  DBG (("get user returned: %s", user));

  if (cfg.try_first_pass || cfg.use_first_pass)
    {
      retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password);
      if (retval != PAM_SUCCESS)
	{
	  DBG (("get password returned error: %s",
		pam_strerror (pamh, retval)));
	  goto done;
	}
      DBG (("get password returned: %s", password));
    }

  if (cfg.use_first_pass && password == NULL)
    {
      DBG (("use_first_pass set and no password, giving up"));
      retval = PAM_AUTH_ERR;
      goto done;
    }

  rc = oath_init ();
  if (rc != OATH_OK)
    {
      DBG (("oath_init() failed (%d)", rc));
      retval = PAM_AUTHINFO_UNAVAIL;
      goto done;
    }

  if (password == NULL)
    {
      retval = pam_get_item (pamh, PAM_CONV, (const void **) &conv);
      if (retval != PAM_SUCCESS)
	{
	  DBG (("get conv returned error: %s", pam_strerror (pamh, retval)));
	  goto done;
	}

      pmsg[0] = &msg[0];
      {
	const char *query_template = "One-time password (OATH) for `%s': ";
	size_t len = strlen (query_template) + strlen (user);
	size_t wrote;

	query_prompt = malloc (len);
	if (!query_prompt)
	  {
	    retval = PAM_BUF_ERR;
	    goto done;
	  }

	wrote = snprintf (query_prompt, len, query_template, user);
	if (wrote < 0 || wrote >= len)
	  {
	    retval = PAM_BUF_ERR;
	    goto done;
	  }

	msg[0].msg = query_prompt;
      }
      msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
      resp = NULL;

      retval = conv->conv (nargs, (const struct pam_message **) pmsg,
			   &resp, conv->appdata_ptr);

      free (query_prompt);
      query_prompt = NULL;

      if (retval != PAM_SUCCESS)
	{
	  DBG (("conv returned error: %s", pam_strerror (pamh, retval)));
	  goto done;
	}

      DBG (("conv returned: %s", resp->resp));

      password = resp->resp;
    }

  if (password)
    password_len = strlen (password);
  else
    {
      DBG (("Could not read password"));
      retval = PAM_AUTH_ERR;
      goto done;
    }

  if (password_len < MIN_OTP_LEN)
    {
      DBG (("OTP too short: %s", password));
      retval = PAM_AUTH_ERR;
      goto done;
    }
  else if (cfg.digits != 0 && password_len < cfg.digits)
    {
      DBG (("OTP shorter than digits=%d: %s", cfg.digits, password));
      retval = PAM_AUTH_ERR;
      goto done;
    }
  else if (cfg.digits == 0 && password_len > MAX_OTP_LEN)
    {
      DBG (("OTP too long (and no digits=): %s", password));
      retval = PAM_AUTH_ERR;
      goto done;
    }
  else if (cfg.digits != 0 && password_len > cfg.digits)
    {
      free (onlypasswd);
      onlypasswd = strdup (password);

      /* user entered their system password followed by generated OTP? */

      onlypasswd[password_len - cfg.digits] = '\0';

      DBG (("Password: %s ", onlypasswd));

      memcpy (otp, password + password_len - cfg.digits, cfg.digits);
      otp[cfg.digits] = '\0';

      retval = pam_set_item (pamh, PAM_AUTHTOK, onlypasswd);
      if (retval != PAM_SUCCESS)
	{
	  DBG (("set_item returned error: %s", pam_strerror (pamh, retval)));
	  goto done;
	}
    }
  else
    {
      strcpy (otp, password);
      password = NULL;
    }

  DBG (("OTP: %s", otp ? otp : "(null)"));

  {
    time_t last_otp;

    rc = oath_authenticate_usersfile (cfg.usersfile,
				      user,
				      otp, cfg.window, onlypasswd, &last_otp);
    DBG (("authenticate rc %d (%s: %s) last otp %s", rc,
	  oath_strerror_name (rc) ? oath_strerror_name (rc) : "UNKNOWN",
	  oath_strerror (rc), ctime (&last_otp)));
  }

  if (rc != OATH_OK)
    {
      DBG (("One-time password not authorized to login as user '%s'", user));
      retval = PAM_AUTH_ERR;
      goto done;
    }

  retval = PAM_SUCCESS;

done:
  oath_done ();
  free (query_prompt);
  free (onlypasswd);
  if (cfg.alwaysok && retval != PAM_SUCCESS)
    {
      DBG (("alwaysok needed (otherwise return with %d)", retval));
      retval = PAM_SUCCESS;
    }
  DBG (("done. [%s]", pam_strerror (pamh, retval)));

  return retval;
}
예제 #12
0
파일: pam-u2f.c 프로젝트: autocracy/pam-u2f
/* PAM entry point for authentication verification */
int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc,
                        const char **argv)
{

  struct passwd *pw = NULL, pw_s;
  const char *user = NULL;

  cfg_t cfg_st;
  cfg_t *cfg = &cfg_st;
  char buffer[BUFSIZE];
  char *buf = NULL;
  char *authfile_dir;
  int authfile_dir_len;
  int pgu_ret, gpn_ret;
  int retval = PAM_IGNORE;
  device_t *devices = NULL;
  unsigned n_devices = 0;

  parse_cfg(flags, argc, argv, cfg);

  if (!cfg->origin) {
    if (!strcpy(buffer, DEFAULT_ORIGIN_PREFIX)) {
      DBG(("Unable to create origin string"));
      goto done;
    }

    if (gethostname
        (buffer + strlen(DEFAULT_ORIGIN_PREFIX),
         BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) {
      DBG(("Unable to get host name"));
      goto done;
    }
    DBG(("Origin not specified, using \"%s\"", buffer));
    cfg->origin = strdup(buffer);
  }

  if (!cfg->origin) {
    DBG(("Unable to allocate memory"));
    goto done;
  }

  if (!cfg->appid) {
    DBG(("Appid not specified, using the same value of origin (%s)",
         cfg->origin));
    cfg->appid = strdup(cfg->origin);
  }

  if (!cfg->appid) {
    DBG(("Unable to allocate memory"));
    goto done;
  }

  if (cfg->max_devs == 0) {
    DBG(("Maximum devices number not set. Using default (%d)", MAX_DEVS));
    cfg->max_devs = MAX_DEVS;
  }

  devices = malloc(sizeof(device_t) * cfg->max_devs);
  if (!devices) {
    DBG(("Unable to allocate memory"));
    return PAM_IGNORE;
  }

  pgu_ret = pam_get_user(pamh, &user, NULL);
  if (pgu_ret != PAM_SUCCESS || user == NULL) {
    DBG(("Unable to access user %s", user));
    free(devices);
    devices = NULL;
    return PAM_CONV_ERR;
  }

  DBG(("Requesting authentication for user %s", user));

  gpn_ret = getpwnam_r(user, &pw_s, buffer, sizeof(buffer), &pw);
  if (gpn_ret != 0 || pw == NULL || pw->pw_dir == NULL
      || pw->pw_dir[0] != '/') {
    DBG(("Unable to retrieve credentials for user %s, (%s)", user,
         strerror(errno)));
    retval = PAM_USER_UNKNOWN;
    goto done;
  }

  DBG(("Found user %s", user));
  DBG(("Home directory for %s is %s", user, pw->pw_dir));

  if (!cfg->auth_file) {
    buf = NULL;
    authfile_dir = secure_getenv(DEFAULT_AUTHFILE_DIR_VAR);
    if (!authfile_dir) {
      DBG(("Variable %s is not set. Using default value ($HOME/.config/)",
           DEFAULT_AUTHFILE_DIR_VAR));
      authfile_dir_len =
          strlen(pw->pw_dir) + strlen("/.config") +
          strlen(DEFAULT_AUTHFILE) + 1;
      buf = malloc(sizeof(char) * (authfile_dir_len));

      if (!buf) {
        DBG(("Unable to allocate memory"));
        retval = PAM_IGNORE;
        goto done;
      }

      strcpy(buf, pw->pw_dir);
      strcat(buf, "/.config");
      strcat(buf, DEFAULT_AUTHFILE);
    } else {
      DBG(("Variable %s set to %s", DEFAULT_AUTHFILE_DIR_VAR,
           authfile_dir));
      authfile_dir_len =
          strlen(authfile_dir) + strlen(DEFAULT_AUTHFILE) + 1;
      buf = malloc(sizeof(char) * (authfile_dir_len));

      if (!buf) {
        DBG(("Unable to allocate memory"));
        retval = PAM_IGNORE;
        goto done;
      }

      strcpy(buf, authfile_dir);
      strcat(buf, DEFAULT_AUTHFILE);
    }

    DBG(("Using default authentication file %s", buf));

    cfg->auth_file = strdup(buf);
    if (!cfg->auth_file) {
      DBG(("Unable to allocate memory"));
      retval = PAM_IGNORE;
      goto done;
    }

    free(buf);
    buf = NULL;
  } else {
    DBG(("Using authentication file %s", cfg->auth_file));
  }
  retval =
      get_devices_from_authfile(cfg->auth_file, user, cfg->max_devs,
                                cfg->debug, devices, &n_devices);
  if (retval != 1) {
    DBG(("Unable to get devices from file %s", cfg->auth_file));
    retval = PAM_AUTHINFO_UNAVAIL;
    goto done;
  }

  if (n_devices == 0) {
    if (cfg->nouserok) {
      DBG(("Found no devices but nouserok specified. Skipping authentication"));
      retval = PAM_SUCCESS;
      goto done;
    } else {
      DBG(("Found no devices. Aborting."));
      retval = PAM_AUTHINFO_UNAVAIL;
      goto done;
    }
  }

  if (cfg->manual == 0) {
    if (cfg->interactive) {
      converse(pamh, PAM_PROMPT_ECHO_ON,
               "Insert your U2F device, then press ENTER.\n");
    }

    retval = do_authentication(cfg, devices, n_devices, pamh);
  } else {
    retval = do_manual_authentication(cfg, devices, n_devices, pamh);
  }

  if (retval != 1) {
    DBG(("do_authentication returned %d", retval));
    retval = PAM_AUTH_ERR;
    goto done;
  }

  retval = PAM_SUCCESS;

done:
  free_devices(devices, n_devices);

  if (buf) {
    free(buf);
    buf = NULL;
  }

  if (cfg->alwaysok && retval != PAM_SUCCESS) {
    DBG(("alwaysok needed (otherwise return with %d)", retval));
    retval = PAM_SUCCESS;
  }
  DBG(("done. [%s]", pam_strerror(pamh, retval)));

  return retval;

}