diff --git a/Makefile b/Makefile index 45fb96c..2caf481 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ build: zond build upload: build - scp -r public/* nathan@hitchhiker-linux.org:/srv/gemini + rsync -rP public/* nathan@hitchhiker-linux.org:/srv/gemini tinylog: zond tinylog diff --git a/content/gemlog/dory_progress_and_misfin_thoughts.gmi b/content/gemlog/dory_progress_and_misfin_thoughts.gmi new file mode 100644 index 0000000..f93ae48 --- /dev/null +++ b/content/gemlog/dory_progress_and_misfin_thoughts.gmi @@ -0,0 +1,69 @@ +Meta( + title: "Dory progress and Misfin thoughts", + summary: Some("Dory successfully sends to the reference server, and I wax poetic about the protocol"), + published: Some(Time( + year: 2023, + month: 6, + day: 6, + hour: 19, + minute: 15, + second: 3, + )), + tags: [ + "misfin", + "email", + "identity", + "rust", + "rustls", + ], +) +--- +I guess I'd call this a milestone achieved. I've successfully sent a couple of Misfin messages to the reference server with a small binary that uses Dory under the hood. Getting there was a little more difficult than I expected, as these things often go. + +=> https://codeberg.org/jeang3nie/sendmsg The sendmsg repository + +### Rustls is a bitch to work with +As it pertains to Gemini (and now Misfin) we're really testing some corner cases in tls library support. Not only are we using Tofu, which is not well supported, but we're also using client certificates to provide identity verification. Rustls puts both of those things well outside the happy path. They're still possible, but you're not going to get any hand holding to wade through the documentation and roll your own certificate verifier. I also discovered a definite bug around client certs, but thankfully there was a workaround. +``` +use rustls::Certificate; +// Here 'c' is assumed to be a `Vec` of the raw der-encoded bytes +// +// This fails with CertificateError::MessageTooShort +let cert = Certificate::read_bytes(&c)?; +// But we can just construct the struct manually and use it, proving that +// the certificate is valid +let cert = Certificate(c); +``` +### Wherein the compiler being pedantic in one way leads me to question my own intelligence +I also ran into a bit of a compiler related issue, that caused me to make a boneheaded mistake. In Rust, you can use enums that map to integer values just like in C. But you can also give an enum member associated data, in which case it's effectively a tagged union. I'm doing that with Misfin status codes in Dory, where there is one 'Status' enum and serveral other enums which represent individual cases for each main status. +``` +pub enum status { + Success = 20, + Redirect(Redirect) = 30, + .. other variants .. +} + +pub enum Redirect ... +``` +The issue was in converting back to u8 from a `Status`. The compiler didn't like `Status::Success as u8` due to the fact that this doesn't work for the other enum members. Using `as u8` does work for a simple enum, just not for one where any of the members have associated data. But what the compiler did accept in my `impl From for u8` was a call to `Into`. +``` +Impl From for u8 { + fn from(value: Status) -> u8 { + match value { + Status::Success => value.into(), + ... +``` +Of course the `Into` trait is provided by reversing the `From` trait, so what I was doing was calling infinite recursion and causing a stack overflow. Yikes, that was stupid. It's also an annoying reminder that while Rust is very good, footguns still exist. This is technically a logic error, not a memory safety error, so the compiler was just like "hey dude, your funeral". + +## Some thoughts on the protocol itself +The further I get into this the more I think it's a good idea. Consider the idea of identity as a baseline. The fact that Email made it so laughably easy to send a message with a spoofed sender address, and in fact the sending address never even had to be a real mailbox, has been one of the major causes of the ridiculous spam problem that has plagued the protocol since the masses got connected. Well in Misfin we're sending a client certificate every time. As long as the servers are actually validating those identities in some way, and that can even be Tofu, then a whole lot of the identity issue is moot. Nobody can spoof your identity unless they have your certificate and key. That means that your ID is your client certificate, and your IP address when sending can change as often as you want because it's just not even looked at in terms of identity. Suddenly the possibility exists that you can send messages from any device and still be recognized as you, while nobody can spoof your identity. If you go that step further and have your client cert signed by the server cert, and use a CA verified server certificate, then the client certificate is pretty much a bulletprooof identity. + +This all occurred to me when I was thinking about how to design Dory in such a way that it would be useful for a single person service and also be able to scale to a server that handled multiple domains, each with multiple users. You still need a way for a client to connect and read their mail, which could be done in a variety of ways, but there's no issue with open relays because the client can just send outgoing messages itself, the way that email was originally supposed to work (you know, when every Unix box was expected to have a `sendmail` binary) but without a lot of the problems that open relays created. That's not to say that if Google ever set up a Misfin service they wouldn't block traffic from whole blocks of IP's, but they wouldn't actually be able to justify why they were doing it the way that they can with Email. + +I'm coming around to some of the other decisions as well. I like that there are no attachments. I think it's better form to just send someone a link to a file somewhere than to actually push that file to their machine. I'm not 100% sold on the message size limit, but in use it's likely not going to be a big issue. Even the little extensions to Gemtext, which are where I was originally most uncomfortable, are well reasoned. + +I've given some thought into how a hypothetical public mail service would look with Misfin. I think one could easily just serve up a person's mailbox over gemini and have them log in using the same client certificate that they use to send messages. Their client could also just send outgoing mail by compiling in the library code to do so and send it directly from whatever machine they're using, even from a phone over a 5g connection (insert whatever number of g's are appropriate for when you're reading this). The remote server which holds your mail could of course allow sending a message that you uploaded via Gemini or Titan, with your certificate, so that you could have in essence a webmail type of service that you use via your favorite Gemini browser. Or one could go all out and do the same with a Web interface, and provide a richer editor experience (although I wouldn't want to write that or use it because I like simple tools). + +For that matter, a fully featured SmallWeb browser could implement the sending portion of Misfin, requiring only access to a receiving server, either on your own home network or in Geminispace somewhere. + +All of these things do come with a small price of course. Anyone using Misfin mail would have to get used to handling their client cert with care. Some might argue that adds a barrier to entry, but considering how crazy most public services are for two factor auth and how they only ever seem to implement it using smartphones, Misfin might actually have an edge for those who don't have a smartphone, but could easily carry around a pendrive with their certificate on it. But we all know how passwords have worked out over time, so I can easily see a bunch of people having a folder on their desktop named "Certificate"... diff --git a/content/gemlog/sourcehut_looks_really_good.gmi b/content/gemlog/sourcehut_looks_really_good.gmi new file mode 100644 index 0000000..388c0f7 --- /dev/null +++ b/content/gemlog/sourcehut_looks_really_good.gmi @@ -0,0 +1,27 @@ +Meta( + title: "Sourcehut looks really good", + summary: Some("I host pretty much everything I\'m working on at Codeberg, but I wonder if I should be on Sourcehut instead based on it\'s features?"), + published: Some(Time( + year: 2023, + month: 6, + day: 8, + hour: 14, + minute: 15, + second: 42, + )), + tags: [ + "git", + "forges", + "email", + ], +) +--- +I've talked about software forges previously on this gemlog. I host pretty much everything I write on Codeberg and I've been overall happy with it, but I find myself more and more thinking sourcehut might have been a better choice. + +I'm definitely oldschool when it comes to computers. My first box was a Tandy TRaSh80, which is to say my earliest computer experience was with a DOS interpretor on an 8-bit POS. I still prefer command line interfaces a lot of the time, even when a gui is really full featured. Codeberg runs Forgejo, a light fork of Gitea. Gitea has obviously been designed from the ground up to be as much like GitHub and GitLab as possible, which makes it immediately comfy for younger devs. In contrast, Sourcehut gives you a really minimal web interface that can fairly be described as "spartan" or even "ugly". But what it does give you, and I like this a lot, is a more traditional way of working that is centered around the command line and email rather than the web browser. + +GitHub has a lot of it's own abstractions over top of git, and those ways of working have largely replaced the traditional way of working with git for a lot of developers. Those abstractions have also been directly copied into both GitLab and Gitea, further perpetuating their adoption. Add to that the hand holding that VScode provides for git operations and I think it's fair to say that an entire generation of developers have zero idea how to actually use git on the command line. + +Now, I was already aware that sourcehut handles patches via `git send-email` instead of the `pull request` push a button in the browser model. But I recently had cause to open a ticket on a project hosted on sr.ht, and discovered that this also works by sending an email. Bonus, you can send patches and open tickets via email, all without having an account on the site. Even bigger bonus, I sent the email from mutt because why yes I am that much of a nerd. And of course it worked and the ticket appeared on the project's page almost immediately. + +I'm sure that this way of working isn't for everybody, but I think that the type of people inhabiting Gemini are probably a little more likely to appreciate this workflow over what has become the "normal" developer workflow in recent years. diff --git a/content/tinylog.gmi b/content/tinylog.gmi index a30e8dd..b872037 100644 --- a/content/tinylog.gmi +++ b/content/tinylog.gmi @@ -4,10 +4,10 @@ Meta( published: Some(Time( year: 2023, month: 6, - day: 6, - hour: 2, - minute: 30, - second: 57, + day: 10, + hour: 13, + minute: 55, + second: 59, )), tags: [ "tinylog", @@ -17,11 +17,26 @@ Meta( Some shorter thoughts and updates that might not warrant a full gemlog entry. I'll probably be using this to post updates on my various projects in a much more regular fashion. => .. Home +## 2023-06-10 13:55 UTC +The latest Dory commits center around an iso-8601 time implementation, which is the format that `timestamp` lines are supposed to use in messages. The spec is of course a little ambiguous, and iso8601 allows dates in one of three formats, with the further distinction that there is both a `basic` formatting and an `extended` formatting, where the difference is the appearance of separators between the fields. I've decided for expediency to only implement `calendar` style dates, which is the traditional yyyy-mm--dd format that we're all used to seeing. +## 2023-06-07 20:36 UTC +Today, after finishing a blog post, I wrote a parser to convert a `&str` to the `Message` struct in Dory. I also added a lot more test coverage, which revealed a few issues to fix. +## 2023-06-06 18:12 UTC +The `sendmsg` binary (using Dory as it's backend) is now able to send Misfin mail to the reference server. This required more debugging skill than it should have due to some issues with both rustls and a compiler issue. Might be good for a full post? Anyway, link to the repository below. + +=>https://codeberg.org/jeang3nie/sendmsg ## 2023-06-06 02:30 UTC Just finished hacking together a small binary that sends Misfin messages from the command line using Dory. Time to grab the reference implementation code and start testing. As an aside, I was thinking that client certs in theory should make identity spoofing next to impossible. That might mean that Misfin clients could just directly shell out to a sendmail-esque binary such as this rather than logging in to a remote server and sending their messages from there. Basically how email was always supposed to work, before all of the spam mitigations broke the ability to deliver mail from unknown random IP addresses. I mean, where you actually send from shouldn't make a bit of difference so long as your certificate goes with you. +## 2023-06-05 14:55 UTC +Began a proof of concept binary project to test out sending Misfin mail using Dory. I should be able to commence testing for interop in the next couple of days. Watch this space for progress reports. +## 2023-06-05 04:25 UTC +Rust 1.70 came out this past week. One of the highlights of this release was the stabilization of the OnceCell and OnceLock types. OnceLock in particular is a big deal because it has the potential to replace the `lazy-static` and `once-cell` crates, for those times when you want to have a lazily evaluated static data structure. + +I just finished a short while ago changing Zond to use the new interface and so far so good. It's nice and simple, with good documentation. + ## 2023-06-04 22:48 UTC I wasn't completely happy with how I had previously setup the workflow for this log, so I did a bit more coding to automate things in a better way than before. I created a small Rust crate for working with Tinylogs and incorporated that into Zond. Now, when you type `zond tinylog` with no other arguments, an editor window will pop up for you to type your thoughts. So long as the temporary file thus created is not empty, the text is added as a new post. This also allows the log to contain a header, which was not possible before.