def _parse_kexdh_init(self, m): # server mode self.e = m.e if (self.e < 1) or (self.e > self.P - 1): raise SshException('Client kex "e" is out of range') K = pow(self.e, self.x, self.P) if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) key = self.protocol.server_key.asbytes() # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) hm = bytearray() hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(key) hm += sshtype.encodeMpint(self.e) hm += sshtype.encodeMpint(self.f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) # sign it sig = self.protocol.server_key.sign_ssh_data(H) # send reply m = mnetpacket.SshKexdhReplyMessage() m.host_key = key m.f = self.f m.signature = sig m.encode() self.protocol.write_packet(m)
def _parse_kexdh_reply(self, m): # The client runs this function. host_key = m.host_key server_f = self.dh.f = m.f if (server_f < 1) or (server_f > self.dh.P - 1): raise SshException('Server kex "f" is out of range') K = self.dh.calculate_k() if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) # H = (V_C || V_S || I_C || I_S || K_S || e || f || K). hm = bytearray() hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(host_key) hm += sshtype.encodeMpint(self.dh.e) hm += sshtype.encodeMpint(server_f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) log.info("Verifying signature...") r = yield from self.protocol.verify_server_key(host_key, m.signature) return r
def _parse_kexdh_reply(self, m): # client mode host_key = m.host_key self.f = m.f if (self.f < 1) or (self.f > self.P - 1): raise SshException('Server kex "f" is out of range') sig = m.signature K = pow(self.f, self.x, self.P) if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) hm = bytearray() hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(host_key) hm += sshtype.encodeMpint(self.e) hm += sshtype.encodeMpint(self.f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) log.info("Verifying signature...") r = yield from self.protocol.verify_server_key(host_key, sig) return r
def _encode_key(self): "Encode the private components into an mnk structure." if (self.p is None) or (self.q is None): raise SshException('Not enough key info to write private key file') """ keylist = [0, self.n, self.e, self.d, self.p, self.q, self.d % (self.p - 1), self.d % (self.q - 1), util.mod_inverse(self.q, self.p)] try: b = BER() b.encode(keylist) except BERException: raise SshException('Unable to create ber encoding of key') return b.asbytes() """ b = bytearray() b += struct.pack("B", 1) # mnk version. b += sshtype.encodeMpint(self.e) b += sshtype.encodeMpint(self.n) b += sshtype.encodeMpint(self.d) b += sshtype.encodeMpint(self.p) b += sshtype.encodeMpint(self.q) return b
def asbytes(self): m = bytearray() m += sshtype.encodeString('ssh-dss') m += sshtype.encodeMpint(self.p) m += sshtype.encodeMpint(self.q) m += sshtype.encodeMpint(self.g) m += sshtype.encodeMpint(self.y) return m
def encode(self, obuf=None): buf = obuf if obuf else bytearray() buf += struct.pack(">L", self.version) buf += sshtype.encodeString(self.ssm) buf += sshtype.encodeMpint(self.sse) buf += sshtype.encodeMpint(self.ssf) buf += struct.pack(">L", self.data_len) buf += self.data_enc
def encode(self, obuf=None): buf = obuf if obuf else bytearray() buf += struct.pack(">L", self.version) buf += sshtype.encodeString(self.ssm) buf += sshtype.encodeMpint(self.sse) buf += sshtype.encodeMpint(self.ssf) buf += sshtype.encodeBinary(self.signature) buf += struct.pack(">L", self.data_len) buf += self.data_enc
def asbytes(self): m = self.__public_key_bytes if m: return m m = bytearray() m += sshtype.encodeString('ssh-rsa') m += sshtype.encodeMpint(self.e) m += sshtype.encodeMpint(self.n) self.__public_key_bytes = m return m
def _dmail_auto_publish(self, dmail_address): data_rw = yield from self.engine.tasks.send_get_data(\ dmail_address.site_key, retry_factor=100) if data_rw.data: if log.isEnabledFor(logging.DEBUG): log.debug("Succeeded in fetching dmail site [{}]; won't"\ " auto-publish."\ .format(mbase32.encode(dmail_address.site_key))) return if log.isEnabledFor(logging.INFO): log.info("Failed to fetch dmail site [{}]; republishing."\ .format(mbase32.encode(dmail_address.site_key))) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) dh = dhgroup14.DhGroup14() dh.x = sshtype.parseMpint(dmail_address.keys[0].x)[1] dh.generate_e() dms = dmail.DmailSite() root = dms.root root["ssm"] = "mdh-v1" root["sse"] = base58.encode(sshtype.encodeMpint(dh.e)) root["target"] =\ mbase32.encode(dmail_address.keys[0].target_key) root["difficulty"] = int(dmail_address.keys[0].difficulty) storing_nodes =\ yield from self._dmail_engine.publish_dmail_site(private_key, dms) if log.isEnabledFor(logging.INFO): log.info("Republished Dmail site with [{}] storing nodes."\ .format(storing_nodes))
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.host_key) nbuf += sshtype.encodeMpint(self.f) nbuf += sshtype.encodeBinary(self.signature) return nbuf
def generate_ss(self): self.dh = dh = dhgroup14.DhGroup14() dh.generate_x() dh.generate_e() if log.isEnabledFor(logging.INFO): log.info("dmail e=[{}].".format(dh.e)) self.root["ssm"] = _dh_method_name self.root["sse"] = base58.encode(sshtype.encodeMpint(dh.e))
def generateKey(self, extra, needed_bytes): assert isinstance(extra, bytes) and len(extra) == 1 buf = bytearray() buf += sshtype.encodeMpint(self.k) buf += self.h buf += extra buf += self.session_id r = sha1(buf).digest() while len(r) < needed_bytes: buf.clear() buf += sshtype.encodeMpint(self.k) buf += self.h buf += r r += sha1(buf).digest() return r[:needed_bytes]
def _parse_kexdh_init(self, m): # The server runs this function. client_e = self.dh.f = m.e if (client_e < 1) or (client_e > self.dh.P - 1): raise SshException("Client kex 'e' is out of range") K = self.dh.calculate_k() if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) key = self.protocol.server_key.asbytes() # H = (V_C || V_S || I_C || I_S || K_S || e || f || K). hm = bytearray() hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(key) hm += sshtype.encodeMpint(client_e) hm += sshtype.encodeMpint(self.dh.e) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) # Sign it. sig = self.protocol.server_key.sign_ssh_data(H) # Send reply. m = mnp.SshKexdhReplyMessage() m.host_key = key m.f = self.dh.e m.signature = sig m.encode() self.protocol.write_packet(m)
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.data) nbuf += struct.pack(">L", self.original_size) if self.version is not None: nbuf += sshtype.encodeMpint(self.version) nbuf += sshtype.encodeBinary(self.signature) if self.epubkey: nbuf += sshtype.encodeBinary(self.epubkey) nbuf += struct.pack(">L", self.pubkeylen) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.data) nbuf += struct.pack("?", self.targeted) if self.pubkey: # Updateable keys. nbuf += sshtype.encodeBinary(self.pubkey) nbuf += sshtype.encodeBinary(self.path_hash) nbuf += sshtype.encodeMpint(self.version) nbuf += sshtype.encodeBinary(self.signature) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.node_id) nbuf += struct.pack("B", self.data_mode.value) nbuf += struct.pack("?", self.version is not None) if self.version is not None: nbuf += sshtype.encodeMpint(self.version) if self.significant_bits: nbuf += struct.pack(">H", self.significant_bits) if self.target_key: nbuf += sshtype.encodeBinary(self.target_key) return nbuf
def dbcall(): with self.db.open_session() as sess: dmailaddress = db.DmailAddress() dmailaddress.site_key = data_key dmailaddress.site_privatekey = privkey._encode_key() dmailkey = db.DmailKey() dmailkey.x = sshtype.encodeMpint(dms.dh.x) dmailkey.target_key = mbase32.decode(dms.root["target"]) dmailkey.difficulty = difficulty dmailaddress.keys.append(dmailkey) sess.add(dmailaddress) sess.commit()
def dbcall(): with self.db.open_session() as sess: dmailaddress = db.DmailAddress() dmailaddress.site_key = data_key dmailaddress.site_privatekey = privkey._encode_key() dmailaddress.scan_interval = 60 dmailkey = db.DmailKey() dmailkey.x = sshtype.encodeMpint(dms.dh.x) dmailkey.target_key = mbase32.decode(dms.root["target"]) dmailkey.difficulty = difficulty dmailaddress.keys.append(dmailkey) sess.add(dmailaddress) sess.commit()
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeMpint(self.e) return nbuf
def serve_get(dispatcher, rpath): global top_tags log.info("Service .dmail request.") req = rpath[len(s_dmail) :] # if log.isEnabledFor(logging.INFO): # log.info("req=[{}].".format(req)) if req == "" or req == "/" or req == "/goto_new_mail" or req.startswith("/wrapper/"): cacheable = False if req == "/goto_new_mail": tag = "Inbox" addr = yield from _load_first_address_with_new_mail(dispatcher) if addr: log.info("NEW") addr_enc = mbase32.encode(addr.site_key) else: log.info("NO NEW") addr_enc = "" qline = None elif req.startswith("/wrapper/"): params = req[9:] pq = params.find("?") if pq != -1: qline = params[pq + 1 :] params = params[:pq] else: qline = None p0 = params.find("/") if p0 == -1: p0 = len(params) tag = "Inbox" else: tag = params[p0 + 1 :] addr_enc = params[:p0] if addr_enc: cacheable = True if dispatcher.handle_cache(req): return else: tag = "Inbox" addr_enc = "" qline = None if not addr_enc: dmail_address = yield from _load_default_dmail_address(dispatcher) if dmail_address: addr_enc = mbase32.encode(dmail_address.site_key) msg_list = None if qline: eparams = parse_qs(qline) msg_list = eparams.get("msg_list") if msg_list: msg_list = msg_list[0] if not msg_list: msg_list = "morphis://.dmail/msg_list/" + addr_enc + "/" + tag template = templates.dmail_page_wrapper[0] template = template.format(tag=tag, addr=addr_enc, msg_list_iframe_url=msg_list) if cacheable: dispatcher.send_content([template, req]) else: dispatcher.send_content(template) return if req == "/style.css": dispatcher.send_content(templates.dmail_css, content_type="text/css") elif req == "/logo": template = templates.dmail_logo[0] current_version = dispatcher.node.morphis_version latest_version_number = dispatcher.latest_version_number if latest_version_number and current_version != latest_version_number: version_str = '<span class="strikethrough nomargin">{}</span>]' ' [<a href="{}{}">GET {}</a>'.format( current_version, dispatcher.handler.maalstroom_url_prefix_str, "sp1nara3xhndtgswh7fznt414we4mi3y6kdwbkz4jmt8ocb6" "x4w1faqjotjkcrefta11swe3h53dt6oru3r13t667pr7" "cpe3ocxeuma/latest_version", latest_version_number, ) else: version_str = current_version connections = dispatcher.connection_count if connections == 1: connection_str = "1 Connection" else: connection_str = str(connections) + " Connections" template = template.format(version=version_str, connections=connection_str) dispatcher.send_content(template) elif req.startswith("/nav/"): params = req[5:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] template = templates.dmail_nav[0] template = template.format(csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag) dispatcher.send_content(template) elif req.startswith("/aside/"): params = req[7:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] addr = mbase32.decode(addr_enc) template = templates.dmail_aside[0] fmt = {} for top_tag in top_tags: active = top_tag == tag unread_count = yield from _count_unread_dmails(dispatcher, addr, top_tag) fmt[top_tag + "_active"] = "active-mailbox" if active else "" fmt[top_tag + "_unread_count"] = unread_count if unread_count else "" fmt[top_tag + "_unread_class"] = ("active-notify" if active else "inactive-notify") if unread_count else "" tags = yield from _load_tags(dispatcher, top_tags) tag_rows = [] unquoted_tag = unquote(tag) for tag in tags: if unquoted_tag == tag.name: active = " active_tag" else: active = "" row = ( '<li class="bullet{active}"><span class="mailbox-pad">' '<a href="morphis://.dmail/wrapper/{addr}/{tag}">{tag}</a>' "</span></li>".format(active=active, addr=addr_enc, tag=tag.name) ) tag_rows.append(row) template = template.format( csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag, tag_rows="".join(tag_rows), **fmt ) acharset = dispatcher.get_accept_charset() dispatcher.send_content(template) elif req.startswith("/msg_list/list/"): params = req[15:] p0 = params.index("/") addr_enc = params[:p0] tag = unquote(params[p0 + 1 :]) template = templates.dmail_msg_list_list_start[0] addr_heading = "TO" if tag in ("Outbox", "Sent", "Drafts") else "FROM" if tag == "Inbox" or tag == "": unread_check = '<meta target="self" http-equiv="refresh" content="60"/>' else: unread_check = "" template = template.format(unread_check=unread_check, addr_heading=addr_heading) acharset = dispatcher.get_accept_charset() dispatcher.send_partial_content(template, True, content_type="text/html; charset={}".format(acharset)) yield from _list_dmails_for_tag(dispatcher, addr_enc, unquote(tag)) dispatcher.send_partial_content(templates.dmail_msg_list_list_end[0]) dispatcher.end_partial_content() elif req.startswith("/msg_list/"): params = req[10:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] if dispatcher.handle_cache(req): return if tag == "Trash": empty_trash_button_class = "link-button" else: empty_trash_button_class = "display_none" template = templates.dmail_msg_list[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, tag=unquote(tag), addr=addr_enc, empty_trash_button_class=empty_trash_button_class, ) dispatcher.send_content([template, req]) elif req == "/new_mail": template = templates.dmail_new_mail[0] unread_count = yield from _count_unread_dmails(dispatcher) template = template.format(unread_count=unread_count) dispatcher.send_content(template) elif req.startswith("/images/"): dispatcher.send_content(templates.imgs[req[8:]]) elif req.startswith("/tag/view/list/"): params = req[15:] p0 = params.index("/") tag = params[:p0] addr_enc = params[p0 + 1 :] if log.isEnabledFor(logging.INFO): log.info("Viewing dmails with tag [{}] for address [{}].".format(tag, addr_enc)) start = templates.dmail_tag_view_list_start.replace(b"${TAG_NAME}", tag.encode()) # FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. start = start.replace(b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(b"${DMAIL_ADDRESS2}", "{}...".format(addr_enc[:32]).encode()) acharset = dispatcher.get_accept_charset() dispatcher.send_partial_content(start, True, content_type="text/html; charset={}".format(acharset)) yield from _list_dmails_for_tag(dispatcher, mbase32.decode(addr_enc), tag) dispatcher.send_partial_content(templates.dmail_tag_view_list_end) dispatcher.end_partial_content() elif req.startswith("/read/content/"): params = req[14:] msg_dbid = params dm = yield from _load_dmail(dispatcher, msg_dbid, fetch_parts=True) dmail_text = _format_dmail_content(dm) acharset = dispatcher.get_accept_charset() dispatcher.send_content(dmail_text.encode(acharset), content_type="text/plain; charset={}".format(acharset)) elif req.startswith("/read/subject/"): params = req[14:] msg_dbid = params dm = yield from _load_dmail(dispatcher, msg_dbid) acharset = dispatcher.get_accept_charset() dispatcher.send_content(dm.subject.encode(acharset), content_type="text/plain; charset={}".format(acharset)) elif req.startswith("/read/"): params = req[6:] p0 = params.index("/") p1 = params.index("/", p0 + 1) addr_enc = params[:p0] tag = params[p0 + 1 : p1] msg_dbid = params[p1 + 1 :] def processor(sess, dm): dm.read = True return True dm = yield from _process_dmail_message(dispatcher, msg_dbid, processor, fetch_parts=True, fetch_tags=True) if dm.hidden: trash_msg = "REMOVE FROM TRASH" else: trash_msg = "MOVE TO TRASH" safe_reply_subject = generate_safe_reply_subject(dm) if dm.sender_dmail_key: sender_addr = mbase32.encode(dm.sender_dmail_key) if dm.sender_valid: sender_class = "valid_sender" else: sender_class = "invalid_sender" else: sender_addr = "[Anonymous]" sender_class = "valid_sender" if dm.destination_dmail_key: dest_addr_enc = mbase32.encode(dm.destination_dmail_key) dest_class = "" else: dest_addr_enc = "" dest_class = " display_none" unquoted_tag = unquote(tag) existing_tag_rows = [] if len(dm.tags) > 1: remove_tag_class = "" for etag in dm.tags: if etag.name == unquoted_tag: selected = "selected " else: selected = "" row = '<option {selected}value"{tag_id}">{tag_name}</option>'.format( selected=selected, tag_id=etag.id, tag_name=etag.name ) existing_tag_rows.append(row) else: remove_tag_class = "display_none" current_tag_names = [x.name for x in dm.tags] current_tag_names.extend(top_tags) current_tag_names.remove("Inbox") tags = yield from _load_tags(dispatcher, current_tag_names) available_tag_rows = [] for atag in tags: row = '<option value"{tag_id}">{tag_name}</option>'.format(tag_id=atag.id, tag_name=atag.name) available_tag_rows.append(row) template = templates.dmail_read[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag, safe_reply_subject=safe_reply_subject, trash_msg=trash_msg, msg_id=msg_dbid, sender_class=sender_class, sender=sender_addr, dest_class=dest_class, dest_addr=dest_addr_enc, date=mutil.format_human_no_ms_datetime(dm.date), remove_tag_class=remove_tag_class, existing_tags="".join(existing_tag_rows), available_tags="".join(available_tag_rows), ) dispatcher.send_content(template) elif req.startswith("/compose/"): if len(req) > 8 and req[8] == "/": params = req[9:] else: params = req[8:] p0 = params.find("?") if p0 != -1: eparams = parse_qs(params[p0 + 1 :]) subject = eparams.get("subject") if subject: subject = subject[0].replace('"', """) else: subject = "" sender_addr_enc = eparams.get("sender") if sender_addr_enc: sender_addr_enc = sender_addr_enc[0] else: sender_addr_enc = "" message_text = eparams.get("message") if message_text: message_text = message_text[0] else: message_text = "" else: subject = "" sender_addr_enc = "" message_text = "" p0 = len(params) dest_addr_enc = params[:p0] autofocus_fields = {"dest_addr_autofocus": "", "subject_autofocus": "", "message_text_autofocus": ""} if not dest_addr_enc: autofocus_fields["dest_addr_autofocus"] = " autofocus" elif not subject: autofocus_fields["subject_autofocus"] = " autofocus" elif not message_text: autofocus_fields["message_text_autofocus"] = " autofocus" addrs = yield from _list_dmail_addresses(dispatcher) if sender_addr_enc: sender_addr = mbase32.decode(sender_addr_enc) default_id = None else: sender_addr = None default_id = yield from _load_default_dmail_address_id(dispatcher) if not default_id: owner_if_anon_id = "" from_addr_options = [] for addr in addrs: if sender_addr: selected = addr.site_key.startswith(sender_addr) elif default_id: selected = addr.id == default_id else: selected = False if selected: option = '<option value="{}" selected>{}</option>' owner_if_anon_id = addr.id else: option = '<option value="{}">{}</option>' addr_enc = mbase32.encode(addr.site_key) from_addr_options.append(option.format(addr.id, addr_enc)) from_addr_options.append("<option value=" ">[Anonymous]</option>") from_addr_options = "".join(from_addr_options) template = templates.dmail_compose[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, delete_class="display_none", owner_if_anon=owner_if_anon_id, from_addr_options=from_addr_options, dest_addr=dest_addr_enc, subject=subject, message_text=message_text, **autofocus_fields ) acharset = dispatcher.get_accept_charset() dispatcher.send_content(template, content_type="text/html; charset={}".format(acharset)) elif req == "/address_list": addrs = yield from _list_dmail_addresses(dispatcher) default_id = yield from _load_default_dmail_address_id(dispatcher) csrf_token = dispatcher.client_engine.csrf_token row_template = templates.dmail_address_list_row[0] rows = [] for addr in addrs: site_key_enc = mbase32.encode(addr.site_key) if default_id and addr.id == default_id: set_default_class = "hidden" else: set_default_class = "" if addr.scan_interval: autoscan_link_text = "disable autoscan" autoscan_interval = 0 else: autoscan_link_text = "enable autoscan" autoscan_interval = 60 resp = row_template.format( csrf_token=csrf_token, addr=site_key_enc, addr_dbid=addr.id, set_default_class=set_default_class, autoscan_link_text=autoscan_link_text, autoscan_interval=autoscan_interval, ) rows.append(resp) rows_content = "".join(rows) template = templates.dmail_address_list[0] template = template.format(address_list=rows_content) dispatcher.send_content(template) # Actions. elif req.startswith("/create_tag?"): query = req[12:] qdict = parse_qs(query, keep_blank_values=True) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return tag_name = qdict["tag_name"][0] if not tag_name: dispatcher.send_204() return r = yield from _create_tag(dispatcher, tag_name) redirect = qdict.get("redirect") if r and redirect: dispatcher.send_301(redirect[0]) else: dispatcher.send_204() elif req.startswith("/modify_message_tag?"): query = req[20:] qdict = parse_qs(query, keep_blank_values=True) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return submit = qdict["submit"][0] def processor(sess, dm): if submit == "add_tag": dmail.attach_dmail_tag(sess, dm, qdict["add_tag"][0]) return True elif submit == "move_to_tag": dm.tags.clear() dmail.attach_dmail_tag(sess, dm, qdict["add_tag"][0]) return True elif submit == "remove_tag": if len(dm.tags) <= 1: return False remove_tag = qdict["remove_tag"][0] remove_target = None for tag in dm.tags: if tag.name == remove_tag: remove_target = tag break dm.tags.remove(remove_target) return True else: return False msg_id = qdict["msg_id"][0] dm = yield from _process_dmail_message(dispatcher, msg_id, processor, fetch_tags=True) redirect = qdict.get("redirect") if redirect: dispatcher.send_301(redirect[0]) else: dispatcher.send_204() elif req.startswith("/refresh/"): params = req[9:] p0 = params.index("/") csrf_token = params[:p0] addr_enc = params[p0 + 1 :] if not dispatcher.check_csrf_token(csrf_token): return dmail_address = yield from _load_dmail_address(dispatcher, site_key=mbase32.decode(addr_enc), fetch_keys=True) dispatcher.client_engine.trigger_dmail_scan(dmail_address) dispatcher.send_204() elif req.startswith("/toggle_read/"): params = req[13:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] msg_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dm): dm.read = not dm.read return True yield from _process_dmail_message(dispatcher, msg_dbid, processor) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/toggle_trashed/"): params = req[16:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] msg_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dm): dm.hidden = not dm.hidden return True yield from _process_dmail_message(dispatcher, msg_dbid, processor) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/set_autoscan/"): params = req[14:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) p1 = params.index("/", p0 + 1, pq) csrf_token = params[:p0] addr_id = int(params[p0 + 1 : p1]) interval = int(params[p1 + 1 : pq]) if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, addr): addr.scan_interval = interval return True addr = yield from _process_dmail_address(dispatcher, processor, addr_id, fetch_keys=True) dispatcher.client_engine.update_dmail_autoscan(addr) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/empty_trash/"): params = req[13:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] addr_enc = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return yield from _empty_trash(dispatcher, addr_enc) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/make_address_default/"): params = req[22:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/") csrf_token = params[:p0] addr_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return yield from _set_default_dmail_address(dispatcher, addr_dbid) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() ##### OLD: elif req == "/create_address": if dispatcher.handle_cache(req): return template = templates.dmail_create_address[0] template = template.format(csrf_token=dispatcher.client_engine.csrf_token) dispatcher.send_content([template, req]) elif req.startswith("/address_config/"): params = req[16:] addr_enc = params dmail_address = yield from _load_dmail_address(dispatcher, site_key=mbase32.decode(addr_enc), fetch_keys=True) content = templates.dmail_address_config[0] content = content.replace("{csrf_token}", dispatcher.client_engine.csrf_token) content = content.replace("${DIFFICULTY}", str(dmail_address.keys[0].difficulty)) content = content.replace("${DMAIL_ADDRESS_SHORT}", addr_enc[:32]) content = content.replace("${DMAIL_ADDRESS}", addr_enc) content = content.replace("${PRIVATE_KEY}", base58.encode(dmail_address.site_privatekey)) content = content.replace("${X}", base58.encode(dmail_address.keys[0].x)) content = content.replace("${TARGET_KEY}", base58.encode(dmail_address.keys[0].target_key)) dispatcher.send_content([content, None]) ##### OLD ACTIONS: elif req.startswith("/create_address/make_it_so?"): query = req[27:] qdict = parse_qs(query, keep_blank_values=True) prefix = qdict["prefix"][0] difficulty = int(qdict["difficulty"][0]) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return log.info("prefix=[{}].".format(prefix)) privkey, dmail_key, dms, storing_nodes = yield from _create_dmail_address(dispatcher, prefix, difficulty) dmail_key_enc = mbase32.encode(dmail_key) dispatcher.send_partial_content(templates.dmail_frame_start, True) if storing_nodes: dispatcher.send_partial_content(b"SUCCESS<br/>") else: dispatcher.send_partial_content( "PARTIAL SUCCESS<br/>" "<p>Your Dmail site was generated successfully; however," " it failed to be stored on the network. To remedy this," " simply go to your Dmail address page and click the" ' [<a target="_self" href="morphis://.dmail/' 'address_config/{}">Address Settings</a>] link, and then' ' click the "Republish Dmail Site" button.</p>'.format(dmail_key_enc).encode() ) dispatcher.send_partial_content( '<p>New dmail address: <a href="morphis://.dmail/wrapper/' '{addr_enc}">{addr_enc}</a></p>'.format(addr_enc=dmail_key_enc).encode() ) dispatcher.send_partial_content(templates.dmail_frame_end) dispatcher.end_partial_content() elif req.startswith("/save_address_config/publish?"): query = req[29:] qdict = parse_qs(query, keep_blank_values=True) addr_enc = qdict["dmail_address"][0] difficulty = qdict["difficulty"][0] csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dmail_address): if difficulty != dmail_address.keys[0].difficulty: dmail_address.keys[0].difficulty = difficulty return True else: return False dmail_address = yield from _process_dmail_address( dispatcher, processor, site_key=mbase32.decode(addr_enc), fetch_keys=True ) dh = dhgroup14.DhGroup14() dh.x = sshtype.parseMpint(dmail_address.keys[0].x)[1] dh.generate_e() dms = dmail.DmailSite() root = dms.root root["ssm"] = "mdh-v1" root["sse"] = base58.encode(sshtype.encodeMpint(dh.e)) root["target"] = mbase32.encode(dmail_address.keys[0].target_key) root["difficulty"] = int(difficulty) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) de = dmail.DmailEngine(dispatcher.node.chord_engine.tasks, dispatcher.node.db) storing_nodes = yield from de.publish_dmail_site(private_key, dms) if storing_nodes: dispatcher.send_content( templates.dmail_addr_settings_edit_success_content[0].format(addr_enc, addr_enc[:32]).encode() ) else: dispatcher.send_content( templates.dmail_addr_settings_edit_fail_content[0].format(addr_enc, addr_enc[:32]).encode() ) else: dispatcher.send_error(errcode=400)
def _generate_encryption_key(self, target_key, k): return enc.generate_ID(\ b"The life forms running github are more retarded than any retard!"\ + target_key + sshtype.encodeMpint(k)\ + b"https://github.com/nixxquality/WebMConverter/commit/"\ + b"c1ac0baac06fa7175677a4a1bf65860a84708d67")
def _generate_encryption_key(self, target_key, k): return enc.generate_ID(\ b"The life forms running github are more retarded than any"\ + b" retard!" + target_key + sshtype.encodeMpint(k)\ + b"https://github.com/nixxquality/WebMConverter/commit/"\ + b"c1ac0baac06fa7175677a4a1bf65860a84708d67")
def __serve_get(handler, rpath, done_event): if len(rpath) == len(s_dmail): handler._send_content(pages.dmail_page_content) else: req = rpath[len(s_dmail):] log.info("req=[{}].".format(req)) if req == "/css": handler._send_content(\ pages.dmail_css_content, content_type="text/css") elif req == "/address_list": handler._send_partial_content( pages.dmail_page_content__f1_start, True) site_keys = yield from _list_dmail_addresses(handler) for dbid, site_key in site_keys: site_key_enc = mbase32.encode(site_key) resp = """<span class="nowrap">[<a href="addr/{}">view</a>]"""\ """ {}</span><br/>"""\ .format(site_key_enc, site_key_enc) handler._send_partial_content(resp) handler._send_partial_content(pages.dmail_page_content__f1_end) handler._end_partial_content() elif req.startswith("/compose/form"): dest_addr_enc = req[14:] if len(req) > 14 else "" handler._send_partial_content(\ pages.dmail_compose_dmail_form_start, True) site_keys = yield from _list_dmail_addresses(handler) for dbid, site_key in site_keys: site_key_enc = mbase32.encode(site_key) sender_element = """<option value="{}">{}</option>"""\ .format(dbid, site_key_enc) handler._send_partial_content(sender_element) handler._send_partial_content(\ "<option value="">[Anonymous]</option>") handler._send_partial_content(\ pages.dmail_compose_dmail_form_end.replace(\ b"${DEST_ADDR}", dest_addr_enc.encode())) handler._end_partial_content() elif req.startswith("/compose"): from_addr = req[9:] if len(req) > 9 else "" if from_addr: iframe_src = "../compose/form/{}".format(from_addr).encode() else: iframe_src = "compose/form".encode() content = pages.dmail_compose_dmail_content[0].replace(\ b"${IFRAME_SRC}", iframe_src) handler._send_content([content, None]) elif req.startswith("/addr/view/"): addr_enc = req[11:] start = pages.dmail_addr_view_start.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS_SHORT}", addr_enc[:32].encode()) handler._send_partial_content(start, True) handler._send_partial_content(pages.dmail_addr_view_end) handler._end_partial_content() elif req.startswith("/addr/settings/edit/publish?"): query = req[28:] qdict = urllib.parse.parse_qs(query, keep_blank_values=True) addr_enc = qdict["dmail_address"][0] difficulty = qdict["difficulty"][0] def processor(dmail_address): if difficulty != dmail_address.keys[0].difficulty: dmail_address.keys[0].difficulty = difficulty return True else: return False dmail_address = yield from\ _process_dmail_address(\ handler, mbase32.decode(addr_enc), processor) dh = dhgroup14.DhGroup14() dh.x = sshtype.parseMpint(dmail_address.keys[0].x)[1] dh.generate_e() dms = dmail.DmailSite() root = dms.root root["target"] =\ mbase32.encode(dmail_address.keys[0].target_key) root["difficulty"] = int(difficulty) root["ssm"] = "mdh-v1" root["sse"] = base58.encode(sshtype.encodeMpint(dh.e)) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) r = yield from\ handler.node.chord_engine.tasks.send_store_updateable_key(\ dms.export(), private_key,\ version=int(time.time()*1000), store_key=True) handler._send_content(\ pages.dmail_addr_settings_edit_success_content[0]\ .format(addr_enc, addr_enc[:32]).encode()) elif req.startswith("/addr/settings/edit/"): addr_enc = req[20:] dmail_address = yield from\ _load_dmail_address(handler, mbase32.decode(addr_enc)) content = pages.dmail_addr_settings_edit_content[0].replace(\ b"${DIFFICULTY}",\ str(dmail_address.keys[0].difficulty).encode()) content = content.replace(\ b"${DMAIL_ADDRESS_SHORT}", addr_enc[:32].encode()) content = content.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) content = content.replace(\ b"${PRIVATE_KEY}",\ base58.encode(dmail_address.site_privatekey).encode()) content = content.replace(\ b"${X}", base58.encode(dmail_address.keys[0].x).encode()) content = content.replace(\ b"${TARGET_KEY}",\ base58.encode(dmail_address.keys[0].target_key).encode()) handler._send_content([content, None]) elif req.startswith("/addr/settings/"): addr_enc = req[15:] content = pages.dmail_addr_settings_content[0].replace(\ b"${IFRAME_SRC}",\ "edit/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/addr/"): addr_enc = req[6:] if log.isEnabledFor(logging.INFO): log.info("Viewing dmail address [{}].".format(addr_enc)) content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "view/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/tag/view/list/"): params = req[15:] p0 = params.index('/') tag = params[:p0] addr_enc = params[p0+1:] if log.isEnabledFor(logging.INFO): log.info("Viewing dmails with tag [{}] for address [{}]."\ .format(tag, addr_enc)) start = pages.dmail_tag_view_list_start.replace(\ b"${TAG_NAME}", tag.encode()) #FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. start = start.replace(b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS2}",\ "{}...".format(addr_enc[:32]).encode()) handler._send_partial_content(start, True) yield from\ _list_dmails_for_tag(handler, mbase32.decode(addr_enc), tag) handler._send_partial_content(pages.dmail_tag_view_list_end) handler._end_partial_content() elif req.startswith("/tag/view/"): params = req[10:] content = pages.dmail_tag_view_content[0].replace(\ b"${IFRAME_SRC}", "../list/{}".format(params).encode()) handler._send_content(content) elif req.startswith("/scan/list/"): addr_enc = req[11:] if log.isEnabledFor(logging.INFO): log.info("Viewing inbox for dmail address [{}]."\ .format(addr_enc)) start = pages.dmail_inbox_start.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS2}", "{}...".format(addr_enc[:32]).encode()) handler._send_partial_content(start, True) addr, significant_bits = mutil.decode_key(addr_enc) yield from _scan_new_dmails(handler, addr, significant_bits) handler._send_partial_content(pages.dmail_inbox_end) handler._end_partial_content() elif req.startswith("/scan/"): addr_enc = req[6:] content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "list/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/fetch/view/"): keys = req[12:] p0 = keys.index('/') dmail_addr_enc = keys[:p0] dmail_key_enc = keys[p0+1:] dmail_addr = mbase32.decode(dmail_addr_enc) dmail_key = mbase32.decode(dmail_key_enc) dm = yield from _load_dmail(handler, dmail_key) if dm: valid_sig = dm.sender_valid else: dm, valid_sig =\ yield from _fetch_dmail(handler, dmail_addr, dmail_key) dmail_text = _format_dmail(dm, valid_sig) handler._send_content(\ dmail_text.encode(), content_type="text/plain") elif req.startswith("/fetch/panel/mark_as_read/"): req_data = req[26:] p0 = req_data.index('/') dmail_key_enc = req_data[p0+1:] dmail_key = mbase32.decode(dmail_key_enc) def processor(dmail): dmail.read = not dmail.read return True yield from _process_dmail_message(handler, dmail_key, processor) handler._send_204() elif req.startswith("/fetch/panel/trash/"): req_data = req[20:] p0 = req_data.index('/') dmail_key_enc = req_data[p0+1:] dmail_key = mbase32.decode(dmail_key_enc) def processor(dmail): dmail.hidden = not dmail.hidden return True yield from _process_dmail_message(handler, dmail_key, processor) handler._send_204() elif req.startswith("/fetch/panel/"): req_data = req[13:] content = pages.dmail_fetch_panel_content[0].replace(\ b"${DMAIL_IDS}", req_data.encode()) handler._send_content([content, None]) elif req.startswith("/fetch/wrapper/"): req_data = req[15:] content = pages.dmail_fetch_wrapper[0].replace(\ b"${IFRAME_SRC}",\ "../../view/{}"\ .format(req_data).encode()) #FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. content = content.replace(\ b"${IFRAME2_SRC}",\ "../../panel/{}"\ .format(req_data).encode()) handler._send_content([content, None]) elif req.startswith("/fetch/"): req_data = req[7:] content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "../wrapper/{}".format(req_data).encode()) handler._send_content([content, None]) elif req == "/create_address": handler._send_content(pages.dmail_create_address_content) elif req == "/create_address/form": handler._send_content(pages.dmail_create_address_form_content) elif req.startswith("/create_address/make_it_so?"): query = req[27:] qdict = urllib.parse.parse_qs(query, keep_blank_values=True) prefix = qdict["prefix"][0] difficulty = int(qdict["difficulty"][0]) log.info("prefix=[{}].".format(prefix)) privkey, dmail_key, dms =\ yield from _create_dmail_address(handler, prefix, difficulty) dmail_key_enc = mbase32.encode(dmail_key) handler._send_partial_content(pages.dmail_frame_start, True) handler._send_partial_content(b"SUCCESS<br/>") handler._send_partial_content(\ """<p>New dmail address: <a href="../addr/{}">{}</a></p>"""\ .format(dmail_key_enc, dmail_key_enc).encode()) handler._send_partial_content(pages.dmail_frame_end) handler._end_partial_content() else: handler._handle_error()
def asbytes(self): m = bytearray() m += sshtype.encodeString("ssh-rsa") m += sshtype.encodeMpint(self.e) m += sshtype.encodeMpint(self.n) return m
def __main(): global loop log.info("mcc running.") parser = argparse.ArgumentParser() parser.add_argument(\ "--address",\ help="The address of the Morphis node to connect to.",\ default="127.0.0.1:4250") parser.add_argument(\ "--create-dmail",\ help="Generate and upload a new dmail site.",\ action="store_true") parser.add_argument(\ "--dburl",\ help="Specify the database url to use.") parser.add_argument(\ "--fetch-dmail", help="Fetch dmail for specified key_id.") parser.add_argument(\ "-i",\ help="Read file as stdin.") parser.add_argument("--nn", type=int,\ help="Node instance number.") parser.add_argument(\ "--prefix",\ help="Specify the prefix for various things (currently --create-dmail"\ ").") parser.add_argument(\ "--scan-dmail",\ help="Scan the network for available dmails.") parser.add_argument(\ "--send-dmail",\ help="Send stdin as a dmail with the specified subject. The"\ " sender and recipients may be specified at the beginning of the"\ " data as with email headers: 'from: ' and 'to: '.") parser.add_argument(\ "--stat",\ help="Report node status.",\ action="store_true") parser.add_argument("-l", dest="logconf",\ help="Specify alternate logging.ini [IF SPECIFIED, THIS MUST BE THE"\ " FIRST PARAMETER!].") parser.add_argument(\ "--dmail-target",\ help="Specify the dmail target to validate dmail against.") parser.add_argument(\ "-x",\ help="Specify the x (Diffie-Hellman private secret) to use.") args = parser.parse_args() # Load or generate client mcc key. key_filename = "data/mcc_key-rsa.mnk" if os.path.exists(key_filename): log.info("mcc private key file found, loading.") client_key = rsakey.RsaKey(filename=key_filename) else: log.info("mcc private key file missing, generating.") client_key = rsakey.RsaKey.generate(bits=4096) client_key.write_private_key_file(key_filename) # Connect a Morphis Client (lightweight Node) instance. mc = client.Client(loop, client_key=client_key, address=args.address) r = yield from mc.connect() if not r: log.warning("Connection failed; exiting.") loop.stop() return dbase = init_db(args) de = dmail.DmailEngine(mc, dbase) log.info("Processing command requests...") if args.stat: r = yield from mc.send_command("stat") print(r.decode("UTF-8"), end='') if args.create_dmail: log.info("Creating and uploading dmail site.") privkey, data_key, dms =\ yield from de.generate_dmail_address(args.prefix) print("privkey: {}".format(base58.encode(privkey._encode_key()))) print("x: {}".format(base58.encode(sshtype.encodeMpint(dms.dh.x)))) print("dmail address: {}".format(mbase32.encode(data_key))) if args.send_dmail: log.info("Sending dmail.") if args.i: with open(args.i, "rb") as fh: dmail_data = fh.read().decode() else: dmail_data = stdin.read() if log.isEnabledFor(logging.DEBUG): log.debug("dmail_data=[{}].".format(dmail_data)) yield from de.send_dmail_text(args.send_dmail, dmail_data) if args.scan_dmail: log.info("Scanning dmail address.") addr, sig_bits = mutil.decode_key(args.scan_dmail) def key_callback(key): print("dmail key: [{}].".format(mbase32.encode(key))) yield from de.scan_dmail_address(\ addr, sig_bits, key_callback=key_callback) if args.fetch_dmail: log.info("Fetching dmail for key=[{}].".format(args.fetch_dmail)) key = mbase32.decode(args.fetch_dmail) if args.x: l, x_int = sshtype.parseMpint(base58.decode(args.x)) else: x_int = None dmail_target = args.dmail_target dm, valid_sig = yield from de.fetch_dmail(key, x_int, dmail_target) if not dm: raise Exception("No dmail found.") if not x_int: print("Encrypted dmail data=[\n{}].".format(mutil.hex_dump(dm))) else: print("Subject: {}\n".format(dm.subject)) if dm.sender_pubkey: print("From: {}"\ .format(mbase32.encode(enc.generate_ID(dm.sender_pubkey)))) i = 0 for part in dm.parts: print("DmailPart[{}]:\n mime-type=[{}]\n data=[{}]\n"\ .format(i, part.mime_type, part.data)) i += 1 log.info("Disconnecting.") yield from mc.disconnect() loop.stop()
def __main(): global loop log.info("mcc running.") parser = argparse.ArgumentParser() parser.add_argument(\ "--address",\ help="The address of the Morphis node to connect to.",\ default="127.0.0.1:4250") parser.add_argument(\ "--create-dmail",\ help="Generate and upload a new dmail site.",\ action="store_true") parser.add_argument(\ "--dburl",\ help="Specify the database url to use.") parser.add_argument(\ "--fetch-dmail", help="Fetch dmail for specified key_id.") parser.add_argument(\ "-i",\ help="Read file as stdin.") parser.add_argument("--nn", type=int,\ help="Node instance number.") parser.add_argument(\ "--prefix",\ help="Specify the prefix for various things (currently --create-dmail"\ ").") parser.add_argument(\ "--scan-dmail",\ help="Scan the network for available dmails.") parser.add_argument(\ "--send-dmail",\ help="Send stdin as a dmail with the specified subject. The"\ " sender and recipients may be specified at the beginning of the"\ " data as with email headers: 'from: ' and 'to: '.") parser.add_argument(\ "--stat",\ help="Report node status.",\ action="store_true") parser.add_argument("-l", dest="logconf",\ help="Specify alternate logging.ini [IF SPECIFIED, THIS MUST BE THE"\ " FIRST PARAMETER!].") parser.add_argument(\ "--dmail-target",\ help="Specify the dmail target to validate dmail against.") parser.add_argument(\ "-x",\ help="Specify the x (Diffie-Hellman private secret) to use.") args = parser.parse_args() # Load or generate client mcc key. key_filename = "data/mcc_key-rsa.mnk" if os.path.exists(key_filename): log.info("mcc private key file found, loading.") client_key = rsakey.RsaKey(filename=key_filename) else: log.info("mcc private key file missing, generating.") client_key = rsakey.RsaKey.generate(bits=4096) client_key.write_private_key_file(key_filename) # Connect a Morphis Client (lightweight Node) instance. mc = client.Client(loop, client_key=client_key, address=args.address) r = yield from mc.connect() if not r: log.warning("Connection failed; exiting.") loop.stop() return dbase = init_db(args) de = dmail.DmailEngine(mc, dbase) log.info("Processing command requests...") if args.stat: r = yield from mc.send_command("stat") print(r.decode("UTF-8"), end='') if args.create_dmail: log.info("Creating and uploading dmail site.") privkey, data_key, dms, storing_nodes =\ yield from de.generate_dmail_address(args.prefix) print("privkey: {}".format(base58.encode(privkey._encode_key()))) print("x: {}".format(base58.encode(sshtype.encodeMpint(dms.dh.x)))) print("dmail address: {}".format(mbase32.encode(data_key))) print("storing_nodes=[{}]."\ .format(base58.encode(privkey._encode_key()))) if args.send_dmail: log.info("Sending dmail.") if args.i: with open(args.i, "rb") as fh: dmail_data = fh.read().decode() else: dmail_data = stdin.read() if log.isEnabledFor(logging.DEBUG): log.debug("dmail_data=[{}].".format(dmail_data)) yield from de.send_dmail_text(args.send_dmail, dmail_data) if args.scan_dmail: log.info("Scanning dmail address.") addr, sig_bits = mutil.decode_key(args.scan_dmail) def key_callback(key): print("dmail key: [{}].".format(mbase32.encode(key))) yield from de.scan_dmail_address(\ addr, sig_bits, key_callback=key_callback) if args.fetch_dmail: log.info("Fetching dmail for key=[{}].".format(args.fetch_dmail)) key = mbase32.decode(args.fetch_dmail) if args.x: l, x_int = sshtype.parseMpint(base58.decode(args.x)) else: x_int = None dmail_target = args.dmail_target dm, valid_sig = yield from de.fetch_dmail(key, x_int, dmail_target) if not dm: raise Exception("No dmail found.") if not x_int: print("Encrypted dmail data=[\n{}].".format(mutil.hex_dump(dm))) else: print("Subject: {}\n".format(dm.subject)) if dm.sender_pubkey: print("From: {}"\ .format(mbase32.encode(enc.generate_ID(dm.sender_pubkey)))) i = 0 for part in dm.parts: print("DmailPart[{}]:\n mime-type=[{}]\n data=[{}]\n"\ .format(i, part.mime_type, part.data)) i += 1 log.info("Disconnecting.") yield from mc.disconnect() loop.stop()