diff options
| author | Sven Moritz Hallberg <sm@khjk.org> | 2008-02-12 00:16:23 +0100 | 
|---|---|---|
| committer | Sven Moritz Hallberg <sm@khjk.org> | 2008-02-12 00:16:23 +0100 | 
| commit | 5f4eedefd2a444c213f65283a3d942d6287e6ea2 (patch) | |
| tree | 3d43e80d56750c842b27835036a1cdc4692c2d2b | |
| parent | 8bd697c80fe304b9a63f9e87d4d4a4e3b1a6bebd (diff) | |
- add nonfunctional 'otr forget key' implementation
- add 'color_encrypted' setting
| -rw-r--r-- | irc.c | 5 | ||||
| -rw-r--r-- | otr.c | 120 | ||||
| -rw-r--r-- | query.c | 4 | 
3 files changed, 113 insertions, 16 deletions
| @@ -108,13 +108,14 @@ irc_t *irc_new( int fd )  	set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );  	set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );  	set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); +	set_add( &irc->set, "color_encrypted", "true", set_eval_bool, irc );  	set_add( &irc->set, "debug", "false", set_eval_bool, irc );  	set_add( &irc->set, "default_target", "root", NULL, irc );  	set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );  	set_add( &irc->set, "handle_unknown", "root", NULL, irc ); -	set_add( &irc->set, "halfop_buddies", "false", set_eval_halfop_buddies, irc ); +	set_add( &irc->set, "halfop_buddies", "encrypted", set_eval_halfop_buddies, irc );  	set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); -	set_add( &irc->set, "op_buddies", "false", set_eval_op_buddies, irc ); +	set_add( &irc->set, "op_buddies", "trusted", set_eval_op_buddies, irc );  	set_add( &irc->set, "op_root", "true", set_eval_op_root, irc );  	set_add( &irc->set, "op_user", "true", set_eval_op_user, irc );  	set_add( &irc->set, "password", NULL, passchange, irc ); @@ -93,6 +93,7 @@ struct kgdata {  void yes_keygen(gpointer w, void *data);  void yes_forget_fingerprint(gpointer w, void *data);  void yes_forget_context(gpointer w, void *data); +void yes_forget_key(gpointer w, void *data);  /* helper to make sure accountname and protocol match the incoming "opdata" */  struct im_connection *check_imc(void *opdata, const char *accountname, @@ -129,6 +130,9 @@ void show_fingerprints(irc_t *irc, ConnContext *ctx);  /* find a fingerprint by prefix (given as any number of hex strings) */  Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args); +/* find a private key by fingerprint prefix (given as any number of hex strings) */ +OtrlPrivKey *match_privkey(irc_t *irc, const char **args); +  /* to log out accounts during keygen */  extern void cmd_account(irc_t *irc, char **cmd); @@ -287,7 +291,8 @@ char *otr_handle_message(struct im_connection *ic, const char *handle, const cha  		/* OTR has processed this message */  		ConnContext *context = otrl_context_find(ic->irc->otr_us, handle,  			ic->acc->user, ic->acc->prpl->name, 0, NULL, NULL, NULL); -		if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { +		if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED && +		   set_getbool(&ic->irc->set, "color_encrypted")) {  			/* color according to f'print trust */  			char color;  			const char *trust = context->active_fingerprint->trust; @@ -394,8 +399,8 @@ void op_create_privkey(void *opdata, const char *accountname,  	log_message(LOGLVL_DEBUG, "op_create_privkey '%s' '%s'", accountname, protocol); -	s = g_strdup_printf("oops, no otr privkey for %s/%s - generate one now?", -		accountname, protocol); +	s = g_strdup_printf("oops, no otr privkey for %s - generate one now?", +		accountname);  	query_add(ic->irc, ic, s, yes_keygen, NULL, ic->acc);  } @@ -793,7 +798,7 @@ void cmd_otr_keygen(irc_t *irc, char **args)  	if(otrl_privkey_find(irc->otr_us, a->user, a->prpl->name)) {  		char *s = g_strdup_printf("account %d already has a key, replace it?", n); -		query_add(irc, a->ic, s, yes_keygen, NULL, a); +		query_add(irc, NULL, s, yes_keygen, NULL, a);  	} else {  		otr_keygen(irc, a->user, a->prpl->name);  	} @@ -801,11 +806,11 @@ void cmd_otr_keygen(irc_t *irc, char **args)  void yes_forget_fingerprint(gpointer w, void *data)  { -	struct im_connection *ic = (struct im_connection *)w; +	irc_t *irc = (irc_t *)w;  	Fingerprint *fp = (Fingerprint *)data;  	if(fp == fp->context->active_fingerprint) { -		irc_usermsg(ic->irc, "that fingerprint is active, terminate otr connection first"); +		irc_usermsg(irc, "that fingerprint is active, terminate otr connection first");  		return;  	} @@ -814,12 +819,12 @@ void yes_forget_fingerprint(gpointer w, void *data)  void yes_forget_context(gpointer w, void *data)  { -	struct im_connection *ic = (struct im_connection *)w; +	irc_t *irc = (irc_t *)w;  	ConnContext *ctx = (ConnContext *)data;  	if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { -		irc_usermsg(ic->irc, "active otr connection with %s, terminate it first", -			peernick(ic->irc, ctx->username, ctx->protocol)); +		irc_usermsg(irc, "active otr connection with %s, terminate it first", +			peernick(irc, ctx->username, ctx->protocol));  		return;  	} @@ -828,6 +833,15 @@ void yes_forget_context(gpointer w, void *data)  	otrl_context_forget(ctx);  } +void yes_forget_key(gpointer w, void *data) +{ +	OtrlPrivKey *key = (OtrlPrivKey *)data; +	 +	/* FIXME: For some reason which /completely eludes me/, this call keeps +	   barfing on the gcry_sexp_release inside (invalid pointer free). */ +	otrl_privkey_forget(key); +} +  void cmd_otr_forget(irc_t *irc, char **args)  {  	if(!strcmp(args[1], "fingerprint")) @@ -869,7 +883,7 @@ void cmd_otr_forget(irc_t *irc, char **args)  		otrl_privkey_hash_to_human(human, fp->fingerprint);  		s = g_strdup_printf("about to forget fingerprint %s, are you sure?", human); -		query_add(irc, u->ic, s, yes_forget_fingerprint, NULL, fp); +		query_add(irc, NULL, s, yes_forget_fingerprint, NULL, fp);  	}  	else if(!strcmp(args[1], "context")) @@ -897,12 +911,28 @@ void cmd_otr_forget(irc_t *irc, char **args)  		}  		s = g_strdup_printf("about to forget otr data about %s, are you sure?", args[2]); -		query_add(irc, u->ic, s, yes_forget_context, NULL, ctx); +		query_add(irc, NULL, s, yes_forget_context, NULL, ctx);  	}  	else if(!strcmp(args[1], "key"))  	{ -		irc_usermsg(irc, "n/a: TODO"); +		OtrlPrivKey *key; +		char *s; +		 +		key = match_privkey(irc, ((const char **)args)+2); +		if(!key) { +			/* match_privkey does error messages */ +			return; +		} +		 +		/* TODO: Find out why 'otr forget key' barfs (cf. yes_forget_key) */ +		irc_usermsg(irc, "otr %s %s: not implemented, please edit \x02%s%s.otr_keys\x02 manually :-/", +			args[0], args[1], global.conf->configdir, irc->nick); +		return; + +		s = g_strdup_printf("about to forget the private key for %s/%s, are you sure?", +			key->accountname, key->protocol); +		query_add(irc, NULL, s, yes_forget_key, NULL, key);  	}  	else @@ -1230,6 +1260,72 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args)  	return fp;  } +OtrlPrivKey *match_privkey(irc_t *irc, const char **args) +{ +	OtrlPrivKey *k, *k2; +	char human[45]; +	char prefix[45], *p; +	int n; +	int i,j; +	 +	/* assemble the args into a prefix in standard "human" form */ +	n=0; +	p=prefix; +	for(i=0; args[i]; i++) { +		for(j=0; args[i][j]; j++) { +			char c = toupper(args[i][j]); +			 +			if(n>=40) { +				irc_usermsg(irc, "too many fingerprint digits given, expected at most 40"); +				return NULL; +			} +			 +			if( (c>='A' && c<='F') || (c>='0' && c<='9') ) { +				*(p++) = c; +			} else { +				irc_usermsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); +				return NULL; +			} +			 +			n++; +			if(n%8 == 0) +				*(p++) = ' '; +		} +	} +	*p = '\0'; +	log_message(LOGLVL_DEBUG, "match_privkey '%s'", prefix); +	log_message(LOGLVL_DEBUG, "n=%d strlen(prefix)=%d", n, strlen(prefix)); +	 +	/* find first key which matches the given prefix */ +	n = strlen(prefix); +	for(k=irc->otr_us->privkey_root; k; k=k->next) { +		p = otrl_privkey_fingerprint(irc->otr_us, human, k->accountname, k->protocol); +		if(!p) /* gah! :-P */ +			continue; +		if(!strncmp(prefix, human, n)) +			break; +	} +	if(!k) { +		irc_usermsg(irc, "%s: no match", prefix); +		return NULL; +	} +	 +	/* make sure the match, if any, is unique */ +	for(k2=k->next; k2; k2=k2->next) { +		p = otrl_privkey_fingerprint(irc->otr_us, human, k2->accountname, k2->protocol); +		if(!p) /* gah! :-P */ +			continue; +		if(!strncmp(prefix, human, n)) +			break; +	} +	if(k2) { +		irc_usermsg(irc, "%s: multiple matches", prefix); +		return NULL; +	} +	 +	return k; +} +  void show_general_otr_info(irc_t *irc)  {  	ConnContext *ctx; @@ -147,7 +147,7 @@ void query_answer( irc_t *irc, query_t *q, int ans )  		else  			irc_usermsg( irc, "Accepted: %s", q->question );  		if(q->yes) -			q->yes( q->ic ? q->ic : irc, q->data ); +			q->yes( q->ic ? (gpointer)q->ic : (gpointer)irc, q->data );  	}  	else  	{ @@ -156,7 +156,7 @@ void query_answer( irc_t *irc, query_t *q, int ans )  		else  			irc_usermsg( irc, "Rejected: %s", q->question );  		if(q->no) -			q->no( q->ic ? q->ic : irc, q->data ); +			q->no( q->ic ? (gpointer)q->ic : (gpointer)irc, q->data );  	}  	q->data = NULL; | 
