My Google Summer of Code 2024 Journey with libssh
(Enable the support for OpenSSH certificates as a new method of authentication in libssh)
When I first learned about Google Summer of Code (GSoC), I knew it was the perfect opportunity to merge my interest in open source software with real-world contributions. This year, I had the chance to work on a project that aimed to integrate OpenSSH certificates support into libssh, a multi-platform C library implementing the SSHv2 protocol. From the start, I knew this would be a technically challenging and rewarding experience, and I’m excited to share the journey of how I managed to work with SSH protocols, certificate-based authentication, and open source collaboration.
Why SSH certificate-based authentication?
SSH certificates provide a more secure and manageable alternative to traditional SSH keys for remote access. Unlike individual SSH keys, which need to be manually managed and distributed, SSH certificates allow for centralized control and streamlined key management. Certificates are signed by a trusted Certificate Authority (CA), making them easier to revoke or renew without the need to update every server or user individually. This reduces the risk of key sprawl and simplifies SSH management, especially in large organizations, while improving security by allowing for expiration dates, critical options, and principal-based authentication.
The project and the work prior to GSoC program
The goal of my project was to significantly enhance libssh’s capability to handle OpenSSH certificates. Yes, enhance, because prior to the start of the GSoC program, libssh offered only a limited support, treating certificates as opaque blobs that were simply passed along with the key to compatible servers for authentication. This allowed for only basic interoperability with some compatible OpenSSH servers, lacking both host authentication by libssh clients and user authentication by libssh servers.
Integrating full support for OpenSSH certificates could make libssh a more compelling choice for organizations seeking a more secure and manageable SSH authentication within enterprise environments.
My very first contribution regarded the implementation of the local network address matching in SSH client configuration (only for Linux and FreeBSD systems). Although it may seem unrelated to certificate context, the CIDR matching feature plays a crucial role in validating the source address of those certificates containing a critical option that specifies this requirement.
Here’s the link to the first MR (and related ones):
gitlab.com/libssh/libssh-mirror/-/merge_requests/469 (merged)
gitlab.com/libssh/libssh-mirror/-/merge_requests/499 (merged)
gitlab.com/libssh/libssh-mirror/-/merge_requests/514 (merged)
Starting the Project
The first couple of weeks were a whirlwind of activity as I got familiar with libssh’s extensive codebase and outlined a strategy for implementing OpenSSH certificates. My initial challenges involved parsing the certificate buffer format and handling its various fields such as key ID, serial number, principals, authentication options and signature key (CA) along with the trailing signature. I spent time thoroughly analyzing the protocol which helped me shape my approach to the problem.
Working with certificates required the implementation of a considerable amount of features that were missing in libssh. In particular, I’m referring to several configuration options for both the client and the server. Some of these include:
- Server side: TrustedUserCAKeys, AuthorizedPrincipalsFile, AuthorizedKeysFile, RevokedKeys, CASignatureAlgorithms, UseDNS and HostCertificate.
- Client side: HostRevokedKeys and CASignatureAlgorithms.
These new configuration options can be set in the same way as existing configuration options are set using libssh. As a part of this project, I provided an alternate way of setting the configuration options by adding the “-o” command line option in the libssh’s ssh client and ssh server examples. This command line option can be used to set a variety of configuration options and it uses a format similar to the option format used for configuration files.
libssh Session APIs (see ssh_options_* API functions)
libssh Server APIs (see ssh_bind_options_* API functions)
libssh Client Example
libssh Server Example
Implementing the Core Features
As I progressed, I focused on extending both client and server capabilities to fully negotiate certificate keys. On the client side, I managed to enable libssh clients to propose certificate algorithms during the Key Exchange process. Similarly, on the server side, I ensured it could recognize and negotiate all public key algorithms, including those involving certificates, to complete the exchange seamlessly.
Another important milestone early on was ensuring that libssh could handle @revoked
and @cert-authority
markers in the Known Hosts file format without being problematic from an ABI perspective. The introduction of these markers was mandatory for making certificate-based Host Authentication possible. The client can now authenticate and trust servers by recognizing trusted Certificate Authorities (CAs) and verifying the validity of the received certificate.
As far as the certificate validation is concerned, one of the most significant parts of the project was implementing an appropriate robust validation mechanism. This involved signature verification, expiration dates, revocation lists, and matching certificates against principals, authorized keys and allowed signature algorithms. To this end, I also worked on the creation of a basic method for revoking keys using a flat file that lists revoked keys. These keys can include both certificate keys and plain keys.
In contrast to the client side, which I would say was relatively easier (libssh already supported a way for loading user certificates), implementing certificate-based user authentication on the server side — along with enhancing normal public key authentication— proved more challenging than expected. It required significant groundwork due to the lack of a proper mechanism to load a Host Certificate and parse the Authorized Keys file format while handling all the numerous authentication options, whether from in-line file options or certificate.
User authentication on the server side posed many challenges and issues making it harder than expected. However, this effort led to the successful creation of a new public API that enables the automated authentication and authorization of both plain keys and certificates — capabilities that were previously left to the libssh user to implement.
Here are the links to all the MRs regarding the actual GSoC project:
gitlab.com/libssh/libssh-mirror/-/merge_requests/493 (still in progress)
gitlab.com/libssh/libssh-mirror/-/merge_requests/500 (merged)
gitlab.com/libssh/libssh-mirror/-/merge_requests/527 (still in progress)
Overcoming Challenges
At the start of my GSoC journey, balancing university exams with the project proved to be a significant challenge, causing my progress to slow down initially. Additionally, while I had some prior experience working on personal projects, transitioning to the level of complexity required by libssh was a major shift. Moving from a largely theoretical understanding of the SSH protocol to applying it in a real-world, large-scale open-source project was more demanding than I anticipated. Despite the very detailed work I made while drafting my GSoC proposal, one of the biggest challenges was maintaining a clear vision of how all the components would fit together and determining the right time to integrate them. Getting a solid grasp of the entire process — while ensuring that each part functioned correctly — proved to be more complex than expected.
In addition, implementing robust unit and integration tests, and ensuring portability across various systems introduced further challenges. Testing on different platforms, managing memory safety, and ensuring the stability of the code across different environments required a great deal of effort. Debugging was time-consuming, and I often needed to discuss with my mentors to find the best solutions. Another significant challenge was ensuring that the new certificate support integrated smoothly with libssh’s existing APIs without introducing breaking changes. I carefully validated each implementation and worked closely with my mentors to ensure the new functionality aligned with libssh’s contribution standards and performance expectations.
About my Mentors
GSoC wouldn’t have been the same without the incredible support from my mentors, Jakub Jelen, Eshan Kelkar and Sahana Prasad. Their guidance was invaluable, especially when it came to design decisions and reviewing my work. They provided thoughtful feedback on my merge requests and were always available for discussions at every day hour, whether it was on the technical details of OpenSSH certificates or the broader implications of my work.
Participating in weekly meetings allowed me to stay on track and prioritize my tasks effectively. We discussed progress, blockers, and planned next steps, ensuring that the project remained aligned with the development goals. Their willingness to share insights and knowledge greatly enhanced my learning experience!
What I learned
My GSoC project was an incredible learning experience. Beyond the technical knowledge of SSH protocols and OpenSSH certificates, I learned valuable skills about:
- Collaboration and Communication
- Problem solving and improving C programming skills
- Test-driven Development, as Jakub would say: “untested code is broken code”.
- Time Management
- Growing a passion for contributing to the open-source community
What’s next?
Without a shadow of a doubt, finally see the code merged! Moving forward, I plan to stay involved with the libssh project, helping maintain the codebase and continuing to contribute to open source software. In fact, there are a few things that still need to be implemented, and I would like to address them myself:
- KRL (Key Revocation List) control
- Certificate generation
Conclusion
Participating in GSoC 2024 was a wonderful experience that allowed me to learn new things and hone my programming skills. The journey of adding OpenSSH certificates to libssh was both challenging and educational, and I’m grateful for the opportunity of being part of this community!