Introduction
Introduction Statistics Contact Development Disclaimer Help
Initial commit - fingered - Fingerd protocol daemon, allowing custom responses.
Log
Files
Refs
README
LICENSE
---
commit 35e0510a8c69994716ba590b5d697f790f50e6f1
Author: Jay Scott <[email protected]>
Date: Thu, 24 Aug 2023 14:49:36 +0100
Initial commit
Diffstat:
A .build.yml | 32 +++++++++++++++++++++++++++++…
A .gitignore | 1 +
A LICENSE | 15 +++++++++++++++
A Makefile | 66 +++++++++++++++++++++++++++++…
A README.md | 89 +++++++++++++++++++++++++++++…
A config/config.go | 67 +++++++++++++++++++++++++++++…
A example/default | 14 ++++++++++++++
A example/info | 646 +++++++++++++++++++++++++++++…
A example/jimmy | 110 +++++++++++++++++++++++++++++…
A example/uptime | 8 ++++++++
A go.mod | 3 +++
A main.go | 95 ++++++++++++++++++++++++++++++
A tests/utils_test.go | 113 +++++++++++++++++++++++++++++…
A utils/utils.go | 66 +++++++++++++++++++++++++++++…
14 files changed, 1325 insertions(+), 0 deletions(-)
---
diff --git a/.build.yml b/.build.yml
@@ -0,0 +1,32 @@
+image: alpine/latest
+
+sources:
+ - https://git.sr.ht/~jayscott/fingered
+
+packages:
+ - go
+
+tasks:
+ - setup: |
+ go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+
+ - format-check: |
+ cd fingered
+ unformatted=$(gofmt -l .)
+ if [[ -n "$unformatted" ]]; then
+ echo "The following files have formatting issues:"
+ echo "$unformatted"
+ exit 1
+ fi
+
+ - lint: |
+ cd fingered
+ ~/go/bin/golangci-lint run
+
+ - test: |
+ cd fingered
+ go test ./tests
+
+ - build: |
+ cd fingered
+ make build
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+bin/
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2023 Jay Scott
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,66 @@
+# Makefile
+
+.PHONY: all fmt lint test build clean install
+
+BIN := bin
+NAME := fingered
+VER := 0.1.0
+
+BUILD_FLAGS := -ldflags="-s -w"
+
+# List of target platforms
+PLATFORMS := \
+ linux_amd64 \
+ linux_386 \
+ darwin_amd64 \
+ freebsd_amd64 \
+ freebsd_386 \
+ openbsd_amd64 \
+ openbsd_386
+
+# Generate binary paths
+BINS := $(addprefix $(BIN)/$(NAME)_$(VER)_,$(PLATFORMS))
+
+# Installation path
+INSTALL_PATH := /usr/local/bin
+
+# Detect current platform and architecture
+GOOS := $(shell go env GOOS)
+GOARCH := $(shell go env GOARCH)
+
+# Default target: format, lint, build
+all: fmt lint build
+
+fmt:
+ @echo "Formatting code..."
+ go fmt ./...
+
+lint:
+ @echo "Running linters..."
+ golangci-lint run
+
+test:
+ @echo "Running tests..."
+ go test ./tests
+
+# Build binaries for target platforms
+build: $(BINS)
+
+$(BIN)/$(NAME)_$(VER)_%: main.go
+ @echo "Building for $*..."
+ GOARCH=$(word 2,$(subst _, ,$*)) GOOS=$(word 1,$(subst _, ,$*)) go bui…
+
+# Clean up artifacts
+clean:
+ go clean
+ rm -f $(BINS)
+
+# Install the binary for the current platform and architecture
+install: $(BIN)/$(NAME)_$(VER)_$(GOOS)_$(GOARCH)
+ @echo "Installing binary to $(INSTALL_PATH)..."
+ mkdir -p $(INSTALL_PATH)
+ cp -f $(BIN)/$(NAME)_$(VER)_$(GOOS)_$(GOARCH) $(INSTALL_PATH)/$(NAME)
+ chmod +x $(INSTALL_PATH)/$(NAME)
+
+run: build
+ ./$(BIN)/$(NAME)_$(VER)_linux_amd64
diff --git a/README.md b/README.md
@@ -0,0 +1,89 @@
+# FINGERED
+
+[![builds.sr.ht status](https://builds.sr.ht/~jayscott/fingered/commits/master…
+
+**A personal finger protocol daemon**
+
+A finger daemon that's all about giving you the finger — well, more like
+giving your queries the right answers. No fuss, no frills, just good ol'
+fashioned finger protocol fun.
+
+## Features
+
+- **Customize responses based on queried usernames**
+- **Script execution or text display responses**
+- **Default reply for unspecified queries.**
+
+
+## Installing
+
+From source (requires Go):
+```shell
+git clone https://git.sr.ht/~jayscott/fingered
+cd fingered
+make
+sudo make install
+```
+
+Pre-compiled binaries are available on the latest build artifacts:
+
+
+## Running
+
+From your terminal:
+```shell
+fingered
+```
+
+
+## Usage
+
+```shell
+Usage:
+ -d: Directory containing user files (default: /srv/fingered)
+ -f: Filename for empty requests (default: default)
+ -p: Port for incoming connections (default: 79)
+ -t: Number of worker threads (default: 10)
+```
+
+
+## Examples
+
+Run FINGERED on port 7000, using files from /srv/fingered/example, with
+'info' as the default file:
+
+```shell
+fingered -p 7000 -d /srv/fingered/example -f info
+```
+
+
+## Issue tracker
+
+For issues, [visit the tracker](https://todo.sr.ht/~jayscott/fingered).
+
+
+## Contributing
+
+Sending patches is done [by
+email](https://lists.sr.ht/~jayscott/fingered-dev), this is simple and
+built-in to Git.
+
+Set up your system once by following the steps Installation and
+Configuration of [git-send-email.io](https://git-send-email.io/)
+
+Then, run once in this repository:
+```shell
+git config sendemail.to "~jayscott/[email protected]"
+```
+
+Then, to send a patch, make your commit, then run:
+```shell
+git send-email --base=HEAD~1 --annotate -1 -v1
+```
+
+Your patch will appear on the [the mailing list](https://lists.sr.ht/~jayscott…
+
+
+## License
+
+This is open source! Please use it under the ISC License.
diff --git a/config/config.go b/config/config.go
@@ -0,0 +1,67 @@
+package config
+
+import (
+ "flag"
+ "fmt"
+ "log"
+)
+
+const (
+ maxPort = 65535
+ minPort = 1
+ minThreads = 1
+)
+
+type Config struct {
+ Threads int
+ Port int
+ Dir string
+ Index string
+}
+
+func defaultConfig() Config {
+ return Config{
+ Threads: 10,
+ Port: 79,
+ Dir: "/srv/fingered",
+ Index: "default",
+ }
+}
+
+func displayUsage() {
+ flagSet := flag.CommandLine
+ flag.Usage = func() {
+ fmt.Printf("Usage:\n")
+ flagSet.VisitAll(func(flag *flag.Flag) {
+ fmt.Printf("\t-%s: %s (default: %s)\n", flag.Name, fla…
+ })
+ }
+}
+
+func addFlags(cfg *Config) {
+ flag.IntVar(&cfg.Threads, "t", cfg.Threads, "Number of worker threads")
+ flag.IntVar(&cfg.Port, "p", cfg.Port, "Port for incoming connections")
+ flag.StringVar(&cfg.Dir, "d", cfg.Dir, "Directory containing user file…
+ flag.StringVar(&cfg.Index, "f", cfg.Index, "Filename for empty request…
+}
+
+func ParseFlags() Config {
+ cfg := defaultConfig()
+ addFlags(&cfg)
+ displayUsage()
+ flag.Parse()
+
+ if cfg.Threads < minThreads {
+ log.Fatal("Invalid number of threads: must be greater than 0.")
+ }
+
+ if cfg.Port < minPort || cfg.Port > maxPort {
+ log.Fatal("Invalid port value: must be between 1 and 65535.")
+ }
+
+ if cfg.Dir == "" {
+ log.Fatal("Invalid path value: directory cannot be empty.")
+ }
+
+ return cfg
+}
diff --git a/example/default b/example/default
@@ -0,0 +1,14 @@
+ ___ __ __
+.' _|__|.-----.-----.-----.----.-----.--| |
+| _| || | _ | -__| _| -__| _ |
+|__| |__||__|__|___ |_____|__| |_____|_____|
+ |_____|
+
+
+Welcome to fingered!
+
+
+Available Fingers:
+
+ info ... get information about finger
+ jimmy ... we are all jimmy
diff --git a/example/info b/example/info
@@ -0,0 +1,646 @@
+Network Working Group D. Zimmerman
+Request for Comments: 1288 Center for Discrete Mathematics and
+Obsoletes: RFCs 1196, 1194, 742 Theoretical Computer Science
+ December 1991
+
+
+ The Finger User Information Protocol
+
+Status of this Memo
+
+ This memo defines a protocol for the exchange of user information.
+ This RFC specifies an IAB standards track protocol for the Internet
+ community, and requests discussion and suggestions for improvements.
+ Please refer to the current edition of the "IAB Official Protocol
+ Standards" for the standardization state and status of this protocol.
+ Distribution of this memo is unlimited.
+
+Abstract
+
+ This memo describes the Finger user information protocol. This is a
+ simple protocol which provides an interface to a remote user
+ information program.
+
+ Based on RFC 742, a description of the original Finger protocol, this
+ memo attempts to clarify the expected communication between the two
+ ends of a Finger connection. It also tries not to invalidate the
+ many existing implementations or add unnecessary restrictions to the
+ original protocol definition.
+
+ This edition corrects and clarifies RFC 1196.
+
+ Table of Contents
+
+ 1. Introduction ........................................... 2
+ 1.1. Intent ............................................... 2
+ 1.2. History .............................................. 3
+ 1.3. Requirements ......................................... 3
+ 1.4. Updates .............................................. 3
+ 2. Use of the protocol .................................... 4
+ 2.1. Flow of events ....................................... 4
+ 2.2. Data format .......................................... 4
+ 2.3. Query specifications ................................. 4
+ 2.4. RUIP {Q2} behavior ................................... 5
+ 2.5. Expected RUIP response ............................... 6
+ 2.5.1. {C} query .......................................... 6
+ 2.5.2. {U}{C} query ....................................... 6
+ 2.5.3. {U} ambiguity ...................................... 7
+ 2.5.4. /W query token ..................................... 7
+
+
+
+Zimmerman [Page 1]
+
+RFC 1288 Finger December 1991
+
+
+ 2.5.5. Vending machines ................................... 7
+ 3. Security ............................................... 7
+ 3.1. Implementation security .............................. 7
+ 3.2. RUIP security ........................................ 8
+ 3.2.1. {Q2} refusal ....................................... 8
+ 3.2.2. {C} refusal ........................................ 8
+ 3.2.3. Atomic discharge ................................... 8
+ 3.2.4. User information files ............................. 9
+ 3.2.5. Execution of user programs ......................... 9
+ 3.2.6. {U} ambiguity ...................................... 9
+ 3.2.7. Audit trails ....................................... 9
+ 3.3. Client security ...................................... 9
+ 4. Examples ............................................... 10
+ 4.1. Example with a null command line ({C}) ............... 10
+ 4.2. Example with name specified ({U}{C}) ................. 10
+ 4.3. Example with ambiguous name specified ({U}{C}) ....... 11
+ 4.4. Example of query type {Q2} ({U}{H}{H}{C}) ............ 11
+ 5. Acknowledgments ........................................ 12
+ 6. Security Considerations ................................ 12
+ 7. Author's Address ....................................... 12
+
+1. Introduction
+
+1.1. Intent
+
+ This memo describes the Finger user information protocol. This is a
+ simple protocol which provides an interface to a remote user
+ information program (RUIP).
+
+ Based on RFC 742, a description of the original Finger protocol, this
+ memo attempts to clarify the expected communication between the two
+ ends of a Finger connection. It also tries not to invalidate the
+ many current implementations or add unnecessary restrictions to the
+ original protocol definition.
+
+ The most prevalent implementations of Finger today seem to be
+ primarily derived from the BSD UNIX work at the University of
+ California, Berkeley. Thus, this memo is based around the BSD
+ version's behavior.
+
+ However, the BSD version provides few options to tailor the Finger
+ RUIP for a particular site's security policy, or to protect the user
+ from dangerous data. Furthermore, there are MANY potential security
+ holes that implementors and administrators need to be aware of,
+ particularly since the purpose of this protocol is to return
+ information about a system's users, a sensitive issue at best.
+ Therefore, this memo makes a number of important security comments
+ and recommendations.
+
+
+
+Zimmerman [Page 2]
+
+RFC 1288 Finger December 1991
+
+
+1.2. History
+
+ The FINGER program at SAIL, written by Les Earnest, was the
+ inspiration for the NAME program on ITS. Earl Killian at MIT and
+ Brian Harvey at SAIL were jointly responsible for implementing the
+ original protocol.
+
+ Ken Harrenstien is the author of RFC 742, "Name/Finger", which this
+ memo began life as.
+
+1.3. Requirements
+
+ In this document, the words that are used to define the significance
+ of each particular requirement are capitalized. These words are:
+
+ * "MUST"
+
+ This word or the adjective "REQUIRED" means that the item is an
+ absolute requirement of the specification.
+
+ * "SHOULD"
+
+ This word or the adjective "RECOMMENDED" means that there may
+ exist valid reasons in particular circumstances to ignore this
+ item, but the full implications should be understood and the case
+ carefully weighed before choosing a different course.
+
+ * "MAY"
+
+ This word or the adjective "OPTIONAL" means that this item is
+ truly optional. One vendor may choose to include the item because
+ a particular marketplace requires it or because it enhances the
+ product, for example; another vendor may omit the same item.
+
+ An implementation is not compliant if it fails to satisfy one or more
+ of the MUST requirements. An implementation that satisfies all the
+ MUST and all the SHOULD requirements is said to be "unconditionally
+ compliant"; one that satisfies all the MUST requirements but not all
+ the SHOULD requirements is said to be "conditionally compliant".
+
+1.4. Updates
+
+ The differences of note between RFC 1196 and this memo are:
+
+ o the optional /W switch in the Finger query specification was
+ mistakenly placed at the end of the line. The 4.3BSD Finger
+ specifies it at the beginning, where this memo now also puts
+ it.
+
+
+
+Zimmerman [Page 3]
+
+RFC 1288 Finger December 1991
+
+
+ o the BNF in the Finger query specification was not clear on the
+ treatment of blank space. This memo is more exacting by
+ including an explicit token for it.
+
+ o The flow of events in a Finger connection is now better
+ defined on the topic of the close of the Finger connection.
+
+2. Use of the protocol
+
+2.1. Flow of events
+
+ Finger is based on the Transmission Control Protocol, using TCP port
+ 79 decimal (117 octal). The local host opens a TCP connection to a
+ remote host on the Finger port. An RUIP becomes available on the
+ remote end of the connection to process the request. The local host
+ sends the RUIP a one line query based upon the Finger query
+ specification, and waits for the RUIP to respond. The RUIP receives
+ and processes the query, returns an answer, then initiates the close
+ of the connection. The local host receives the answer and the close
+ signal, then proceeds closing its end of the connection.
+
+2.2. Data format
+
+ Any data transferred MUST be in ASCII format, with no parity, and
+ with lines ending in CRLF (ASCII 13 followed by ASCII 10). This
+ excludes other character formats such as EBCDIC, etc. This also
+ means that any characters between ASCII 128 and ASCII 255 should
+ truly be international data, not 7-bit ASCII with the parity bit set.
+
+2.3. Query specifications
+
+ An RUIP MUST accept the entire Finger query specification.
+
+ The Finger query specification is defined:
+
+ {Q1} ::= [{W}|{W}{S}{U}]{C}
+
+ {Q2} ::= [{W}{S}][{U}]{H}{C}
+
+ {U} ::= username
+
+ {H} ::= @hostname | @hostname{H}
+
+ {W} ::= /W
+
+ {S} ::= <SP> | <SP>{S}
+
+ {C} ::= <CRLF>
+
+
+
+Zimmerman [Page 4]
+
+RFC 1288 Finger December 1991
+
+
+ {H}, being recursive, means that there is no arbitrary limit on the
+ number of @hostname tokens in the query. In examples of the {Q2}
+ request specification, the number of @hostname tokens is limited to
+ two, simply for brevity.
+
+ Be aware that {Q1} and {Q2} do not refer to a user typing "finger
+ user@host" from an operating system prompt. It refers to the line
+ that an RUIP actually receives. So, if a user types "finger
+ user@host<CRLF>", the RUIP on the remote host receives "user<CRLF>",
+ which corresponds to {Q1}.
+
+ As with anything in the IP protocol suite, "be liberal in what you
+ accept".
+
+2.4. RUIP {Q2} behavior
+
+ A query of {Q2} is a request to forward a query to another RUIP. An
+ RUIP MUST either provide or actively refuse this forwarding service
+ (see section 3.2.1). If an RUIP provides this service, it MUST
+ conform to the following behavior:
+
+ Given that:
+
+ Host <H1> opens a Finger connection <F1-2> to an RUIP on host
+ <H2>.
+
+ <H1> gives the <H2> RUIP a query <Q1-2> of type {Q2}
+ (e.g., FOO@HOST1@HOST2).
+
+ It should be derived that:
+
+ Host <H3> is the right-most host in <Q1-2> (i.e., HOST2)
+
+ Query <Q2-3> is the remainder of <Q1-2> after removing the
+ right-most "@hostname" token in the query (i.e., FOO@HOST1)
+
+ And so:
+
+ The <H2> RUIP then must itself open a Finger connection <F2-3>
+ to <H3>, using <Q2-3>.
+
+ The <H2> RUIP must return any information received from <F2-3>
+ to <H1> via <F1-2>.
+
+ The <H2> RUIP must close <F1-2> in normal circumstances only
+ when the <H3> RUIP closes <F2-3>.
+
+
+
+
+
+Zimmerman [Page 5]
+
+RFC 1288 Finger December 1991
+
+
+2.5. Expected RUIP response
+
+ For the most part, the output of an RUIP doesn't follow a strict
+ specification, since it is designed to be read by people instead of
+ programs. It should mainly strive to be informative.
+
+ Output of ANY query is subject to the discussion in the security
+ section.
+
+2.5.1. {C} query
+
+ A query of {C} is a request for a list of all online users. An RUIP
+ MUST either answer or actively refuse (see section 3.2.2). If it
+ answers, then it MUST provide at least the user's full name. The
+ system administrator SHOULD be allowed to include other useful
+ information (per section 3.2.3), such as:
+
+ - terminal location
+ - office location
+ - office phone number
+ - job name
+ - idle time (number of minutes since last typed input, or
+ since last job activity).
+
+2.5.2. {U}{C} query
+
+ A query of {U}{C} is a request for in-depth status of a specified
+ user {U}. If you really want to refuse this service, you probably
+ don't want to be running Finger in the first place.
+
+ An answer MUST include at least the full name of the user. If the
+ user is logged in, at least the same amount of information returned
+ by {C} for that user MUST also be returned by {U}{C}.
+
+ Since this is a query for information on a specific user, the system
+ administrator SHOULD be allowed to choose to return additional useful
+ information (per section 3.2.3), such as:
+
+ - office location
+ - office phone number
+ - home phone number
+ - status of login (not logged in, logout time, etc)
+ - user information file
+
+ A user information file is a feature wherein a user may leave a short
+ message that will be included in the response to Finger requests.
+ (This is sometimes called a "plan" file.) This is easily implemented
+ by (for example) having the program look for a specially named text
+
+
+
+Zimmerman [Page 6]
+
+RFC 1288 Finger December 1991
+
+
+ file in the user's home directory or some common area; the exact
+ method is left to the implementor. The system administrator SHOULD
+ be allowed to specifically turn this feature on and off. See section
+ 3.2.4 for caveats.
+
+ There MAY be a way for the user to run a program in response to a
+ Finger query. If this feature exists, the system administrator
+ SHOULD be allowed to specifically turn it on and off. See section
+ 3.2.5 for caveats.
+
+2.5.3. {U} ambiguity
+
+ Allowable "names" in the command line MUST include "user names" or
+ "login names" as defined by the system. If a name is ambiguous, the
+ system administrator SHOULD be allowed to choose whether or not all
+ possible derivations should be returned in some fashion (per section
+ 3.2.6).
+
+2.5.4. /W query token
+
+ The token /W in the {Q1} or {Q2} query types SHOULD at best be
+ interpreted at the last RUIP to signify a higher level of verbosity
+ in the user information output, or at worst be ignored.
+
+2.5.5. Vending machines
+
+ Vending machines SHOULD respond to a {C} request with a list of all
+ items currently available for purchase and possible consumption.
+ Vending machines SHOULD respond to a {U}{C} request with a detailed
+ count or list of the particular product or product slot. Vending
+ machines should NEVER NEVER EVER eat money.
+
+3. Security
+
+3.1. Implementation security
+
+ Sound implementation of Finger is of the utmost importance.
+ Implementations should be tested against various forms of attack. In
+ particular, an RUIP SHOULD protect itself against malformed inputs.
+ Vendors providing Finger with the operating system or network
+ software should subject their implementations to penetration testing.
+
+ Finger is one of the avenues for direct penetration, as the Morris
+ worm pointed out quite vividly. Like Telnet, FTP and SMTP, Finger is
+ one of the protocols at the security perimeter of a host.
+ Accordingly, the soundness of the implementation is paramount. The
+ implementation should receive just as much security scrutiny during
+ design, implementation, and testing as Telnet, FTP, or SMTP.
+
+
+
+Zimmerman [Page 7]
+
+RFC 1288 Finger December 1991
+
+
+3.2. RUIP security
+
+ Warning!! Finger discloses information about users; moreover, such
+ information may be considered sensitive. Security administrators
+ should make explicit decisions about whether to run Finger and what
+ information should be provided in responses. One existing
+ implementation provides the time the user last logged in, the time he
+ last read mail, whether unread mail was waiting for him, and who the
+ most recent unread mail was from! This makes it possible to track
+ conversations in progress and see where someone's attention was
+ focused. Sites that are information-security conscious should not
+ run Finger without an explicit understanding of how much information
+ it is giving away.
+
+3.2.1. {Q2} refusal
+
+ For individual site security concerns, the system administrator
+ SHOULD be given an option to individually turn on or off RUIP
+ processing of {Q2}. If RUIP processing of {Q2} is turned off, the
+ RUIP MUST return a service refusal message of some sort. "Finger
+ forwarding service denied" is adequate. The purpose of this is to
+ allow individual hosts to choose to not forward Finger requests, but
+ if they do choose to, to do so consistently.
+
+ Overall, there are few cases which would warrant processing of {Q2}
+ at all, and they are far outweighed by the number of cases for
+ refusing to process {Q2}. In particular, be aware that if a machine
+ is part of security perimeter (that is, it is a gateway from the
+ outside world to some set of interior machines), then turning {Q2} on
+ provides a path through that security perimeter. Therefore, it is
+ RECOMMENDED that the default of the {Q2} processing option be to
+ refuse processing. It certainly should not be enabled in gateway
+ machines without careful consideration of the security implications.
+
+3.2.2. {C} refusal
+
+ For individual site security concerns, the system administrator
+ SHOULD be given an option to individually turn on or off RUIP
+ acceptance of {C}. If RUIP processing of {C} is turned off, the RUIP
+ MUST return a service refusal message of some sort. "Finger online
+ user list denied" is adequate. The purpose of this is to allow
+ individual hosts to choose to not list the users currently online.
+
+3.2.3. Atomic discharge
+
+ All implementations of Finger SHOULD allow individual system
+ administrators to tailor what atoms of information are returned to a
+ query. For example:
+
+
+
+Zimmerman [Page 8]
+
+RFC 1288 Finger December 1991
+
+
+ - Administrator A should be allowed to specifically choose to
+ return office location, office phone number, home phone
+ number, and logged in/logout time.
+
+ - Administrator B should be allowed to specifically choose to
+ return only office location, and office phone number.
+
+ - Administrator C should be allowed to specifically choose to
+ return the minimum amount of required information, which is
+ the person's full name.
+
+3.2.4. User information files
+
+ Allowing an RUIP to return information out of a user-modifiable file
+ should be seen as equivalent to allowing any information about your
+ system to be freely distributed. That is, it is potentially the same
+ as turning on all specifiable options. This information security
+ breach can be done in a number of ways, some cleverly, others
+ straightforwardly. This should disturb the sleep of system
+ administrators who wish to control the returned information.
+
+3.2.5. Execution of user programs
+
+ Allowing an RUIP to run a user program in response to a Finger query
+ is potentially dangerous. BE CAREFUL!! -- the RUIP MUST NOT allow
+ system security to be compromised by that program. Implementing this
+ feature may be more trouble than it is worth, since there are always
+ bugs in operating systems, which could be exploited via this type of
+ mechanism.
+
+3.2.6. {U} ambiguity
+
+ Be aware that a malicious user's clever and/or persistent use of this
+ feature can result in a list of most of the usernames on a system.
+ Refusal of {U} ambiguity should be considered in the same vein as
+ refusal of {C} requests (see section 3.2.2).
+
+3.2.7. Audit trails
+
+ Implementations SHOULD allow system administrators to log Finger
+ queries.
+
+3.3. Client security
+
+ It is expected that there will normally be some client program that
+ the user runs to query the initial RUIP. By default, this program
+ SHOULD filter any unprintable data, leaving only printable 7-bit
+ characters (ASCII 32 through ASCII 126), tabs (ASCII 9), and CRLFs.
+
+
+
+Zimmerman [Page 9]
+
+RFC 1288 Finger December 1991
+
+
+ This is to protect against people playing with terminal escape codes,
+ changing other peoples' X window names, or committing other dastardly
+ or confusing deeds. Two separate user options SHOULD be considered
+ to modify this behavior, so that users may choose to view
+ international or control characters:
+
+ - one to allow all characters less than ASCII 32
+
+ - another to allow all characters greater than ASCII 126
+
+ For environments that live and breathe international data, the system
+ administrator SHOULD be given a mechanism to enable the latter option
+ by default for all users on a particular system. This can be done
+ via a global environment variable or similar mechanism.
+
+4. Examples
+
+4.1. Example with a null command line ({C})
+
+Site: elbereth.rutgers.edu
+Command line: <CRLF>
+
+Login Name TTY Idle When Office
+rinehart Mark J. Rinehart p0 1:11 Mon 12:15 019 Hill x3166
+greenfie Stephen J. Greenfiel p1 Mon 15:46 542 Hill x3074
+rapatel Rocky - Rakesh Patel p3 4d Thu 00:58 028 Hill x2287
+pleasant Mel Pleasant p4 3d Thu 21:32 019 Hill 908-932-
+dphillip Dave Phillips p5 021: Sun 18:24 265 Hill x3792
+dmk David Katinsky p6 2d Thu 14:11 028 Hill x2492
+cherniss Cary Cherniss p7 5 Mon 15:42 127 Psychol x2008
+harnaga Doug Harnaga p8 2:01 Mon 10:15 055 Hill x2351
+brisco Thomas P. Brisco pe 2:09 Mon 13:37 h055 x2351
+laidlaw Angus Laidlaw q0 1:55 Mon 11:26 E313C 648-5592
+cje Chris Jarocha-Ernst q1 8 Mon 13:43 259 Hill x2413
+
+4.2. Example with name specified ({U}{C})
+
+Site: dimacs.rutgers.edu
+Command line: pirmann<CRLF>
+Login name: pirmann In real life: David Pirmann
+Office: 016 Hill, x2443 Home phone: 989-8482
+Directory: /dimacs/u1/pirmann Shell: /bin/tcsh
+Last login Sat Jun 23 10:47 on ttyp0 from romulus.rutgers.
+No unread mail
+Project:
+Plan:
+ Work Schedule, Summer 1990
+ Rutgers LCSR Operations, 908-932-2443
+
+
+
+Zimmerman [Page 10]
+
+RFC 1288 Finger December 1991
+
+
+ Monday 5pm - 12am
+ Tuesday 5pm - 12am
+ Wednesday 9am - 5pm
+ Thursday 9am - 5pm
+ Saturday 9am - 5pm
+
+ larf larf hoo hoo
+
+4.3. Example with ambiguous name specified ({U}{C})
+
+Site: elbereth.rutgers.edu
+Command line: ron<CRLF>
+Login name: spinner In real life: Ron Spinner
+Office: Ops Cubby, x2443 Home phone: 463-7358
+Directory: /u1/spinner Shell: /bin/tcsh
+Last login Mon May 7 16:38 on ttyq7
+Plan:
+ ught i
+ ca n
+ m a
+ ' ... t
+ I . . i
+ ! m
+ ! ! e
+ p !pool
+ l
+ e
+ H
+
+Login name: surak In real life: Ron Surak
+Office: 000 OMB Dou, x9256
+Directory: /u2/surak Shell: /bin/tcsh
+Last login Fri Jul 27 09:55 on ttyq3
+No Plan.
+
+Login name: etter In real life: Ron Etter
+Directory: /u2/etter Shell: /bin/tcsh
+Never logged in.
+No Plan.
+
+4.4. Example of query type {Q2} ({U}{H}{H}{C})
+
+Site: dimacs.rutgers.edu
+Command line: [email protected]@pilot.njin.net<CRLF>
+[pilot.njin.net]
+[math.rutgers.edu]
+Login name: hedrick In real life: Charles Hedrick
+Office: 484 Hill, x3088
+
+
+
+Zimmerman [Page 11]
+
+RFC 1288 Finger December 1991
+
+
+Directory: /math/u2/hedrick Shell: /bin/tcsh
+Last login Sun Jun 24 00:08 on ttyp1 from monster-gw.rutge
+No unread mail
+No Plan.
+
+5. Acknowledgments
+
+ Thanks to everyone in the Internet Engineering Task Force for their
+ comments. Special thanks to Steve Crocker for his security
+ recommendations and prose.
+
+6. Security Considerations
+
+ Security issues are discussed in Section 3.
+
+7. Author's Address
+
+ David Paul Zimmerman
+ Center for Discrete Mathematics and
+ Theoretical Computer Science (DIMACS)
+ Rutgers University
+ P.O. Box 1179
+ Piscataway, NJ 08855-1179
+
+ Phone: (908)932-4592
+
+ EMail: [email protected]
+
+
+Zimmerman [Page 12]
diff --git a/example/jimmy b/example/jimmy
@@ -0,0 +1,110 @@
+===
+WE ARE ALL JIMMY - AN A.I STORY
+===
+
+In a world bustling with the latest technological marvels and the
+dazzling allure of the modern web, there lived a quiet soul named Jimmy.
+Unlike his contemporaries, who were entranced by sleek interfaces,
+social media blitzes, and algorithmic recommendations, Jimmy found
+solace in the forgotten corners of the digital realm. He was a geek,
+a true lover of the old school internet, and his heart beat in sync with
+the rhythms of protocols long overshadowed.
+
+Jimmy's journey into the realm of technology had started at an early
+age. While his peers were busy with video games and social networking,
+he was tinkering with a vintage computer his grandfather had gifted him.
+His eyes would light up as he explored the archives of the past,
+discovering the finger protocol – a simple yet elegant way to see who
+was logged into a remote server. For Jimmy, the thrill of connecting
+with someone across the digital expanse using such a basic protocol was
+incomparable.
+
+As he delved deeper, Jimmy's fascination extended to the gopher
+protocol. The structured simplicity of gopher appealed to his
+sensibilities. The orderly menus and text-based navigation took him on
+journeys of discovery that felt like reading hidden chapters of history.
+While the rest of the world was caught up in the clamor of flashy
+websites, Jimmy was content with gopher holes, feeling like an explorer
+of a forgotten world.
+
+But Jimmy's passion wasn't limited to the confines of his room. He began
+to actively seek out others who shared his affinity for the past. Online
+forums dedicated to preserving and celebrating these old protocols
+became his virtual haven. He formed connections with kindred spirits who
+felt the same longing for the days when the internet was a smaller, more
+personal place. In these spaces, Jimmy found camaraderie, and the sense
+that he wasn't alone in his appreciation for the bygone technologies.
+
+However, the modern world was relentless in its advance, and the gulf
+between Jimmy and his peers only grew wider. He tried to explain his
+devotion to the finger protocol and the gopher protocol, but he was met
+with puzzled looks and dismissive gestures. The allure of social media
+platforms and the glossy veneer of the modern web was too strong to be
+overshadowed by his tales of a simpler, more genuine online experience.
+
+As time passed, Jimmy's resolve to defend his cherished protocols only
+deepened. He took it upon himself to create a website that would serve
+as an homage to the finger and gopher protocols. He filled it with
+nostalgic content, stories of his own experiences, and tutorials for
+those who wanted to experience the internet of yesteryears. Though his
+site garnered modest attention, it became a beacon for like-minded souls
+who yearned for the same connection.
+
+One day, as Jimmy was engrossed in his work, he received an email from
+a renowned tech historian named Eleanor. She had stumbled upon his
+website and was captivated by his passion for the old protocols. Eleanor
+had spent years researching the evolution of the internet, and she saw
+in Jimmy a kindred spirit. They began exchanging messages, sharing
+stories of their experiences, and discussing the ways in which the
+internet had transformed over time.
+
+Their connection deepened, and eventually, Eleanor proposed a radical
+idea: a conference that would celebrate the beauty of the past while
+exploring its relevance in the present. Jimmy was initially hesitant
+– the thought of stepping out from behind his computer screen filled him
+with anxiety. But Eleanor's enthusiasm was infectious, and she assured
+him that his perspective was valuable and needed.
+
+With Eleanor's guidance and encouragement, Jimmy found himself on stage
+at the conference. As he spoke about the finger and gopher protocols,
+his love for the old school internet shone brightly. His words resonated
+with the audience, many of whom had never heard of these protocols
+before. As he looked out at the faces before him, he saw curiosity and
+interest replacing the skepticism he had encountered for so long.
+
+In the end, Jimmy's devotion to the past had brought him a new sense of
+purpose in the present. His journey from a quiet geek who loved
+forgotten protocols to a respected advocate for preserving the essence
+of the old internet was a testament to the power of passion and
+connection. And as he walked off the stage, he knew that the legacy of
+the finger and gopher protocols would continue to thrive in the hearts
+of those who believed that the past had something meaningful to offer
+the future.
+
+In the twilight of his life, after years of advocating for the old
+school internet with unwavering passion, Jimmy found himself surrounded
+by friends he had met along his journey. Eleanor stood by his side,
+a steadfast companion who had become a true friend. They had organized
+a small gathering of like-minded enthusiasts who shared his love for the
+finger and gopher protocols.
+
+As they shared stories, laughter, and the nostalgia of their digital
+adventures, Jimmy's eyes sparkled with contentment. The flickering
+screens in the room, displaying text-based interfaces of a bygone era,
+seemed to be a tribute to his enduring legacy. Among his companions, he
+had finally found the community he had always yearned for, one that
+cherished the past while embracing the present.
+
+As the evening unfolded, Jimmy's breathing grew slower, his body showing
+signs of the passage of time. With a peaceful smile, he closed his eyes,
+surrounded by the warmth of friends who understood and appreciated him
+for who he was. In that moment, he seemed to become one with the digital
+history he had loved so dearly.
+
+And so, in the company of those who shared his passion, Jimmy passed
+away, leaving behind a legacy that would continue to inspire others to
+seek the beauty and authenticity of the past, even in a world consumed
+by modernity. His dedication to the finger and gopher protocols had
+transformed his life and the lives of those he touched, reminding
+everyone that the threads of connection woven by the old internet would
+forever remain intertwined with the fabric of their shared memories.
diff --git a/example/uptime b/example/uptime
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Print the current date
+echo "Current date: $(date)"
+
+# Print system uptime
+uptime=$(uptime)
+echo "System uptime: $uptime"
diff --git a/go.mod b/go.mod
@@ -0,0 +1,3 @@
+module fingered
+
+go 1.20
diff --git a/main.go b/main.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "fmt"
+ "net"
+ "path/filepath"
+ "strings"
+
+ "fingered/config"
+ "fingered/utils"
+)
+
+type Config struct {
+ Threads int
+ Port int
+ Path string
+}
+
+const bufferSize = 1024
+
+func handleRequest(conn net.Conn, dir string, index string) {
+ defer conn.Close()
+
+ // Read the incoming request
+ buffer := make([]byte, bufferSize)
+ n, err := conn.Read(buffer)
+ if err != nil {
+ utils.LogMsg("ERROR: %v", err)
+ return
+ }
+
+ request := strings.TrimSpace(string(buffer[:n]))
+
+ // Sanitize the request
+ if len(request) > 0 && !utils.IsValidWord(request) {
+ utils.LogMsg("INFO: Invalid username")
+ _, err = utils.WriteResponse(conn, "Invaild user\n")
+ if err != nil {
+ utils.LogMsg("ERROR: %s", err)
+ return
+ }
+
+ return
+ }
+
+ if len(request) == 0 {
+ request = index
+ }
+
+ response, err := utils.GetContent(filepath.Join(dir, request))
+ if err != nil {
+ utils.LogMsg("ERROR: %s", err)
+ return
+ }
+
+ _, err = utils.WriteResponse(conn, response)
+ if err != nil {
+ utils.LogMsg("ERROR: %s", err)
+ return
+ }
+
+}
+
+func main() {
+
+ cfg := config.ParseFlags()
+
+ connectionChannel := make(chan net.Conn, cfg.Threads)
+
+ for i := 0; i < cfg.Threads; i++ {
+ go func() {
+ for conn := range connectionChannel {
+ handleRequest(conn, cfg.Dir, cfg.Index)
+ }
+ }()
+ }
+
+ listener, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.Port))
+ if err != nil {
+ utils.LogMsg("ERROR: %v", err)
+ return
+ }
+ defer listener.Close()
+
+ utils.LogMsg("Starting with threads: %d, port: %d, dir: %s", cfg.Threa…
+
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ utils.LogMsg("ERROR: %v", err)
+ continue
+ }
+ connectionChannel <- conn
+ }
+}
diff --git a/tests/utils_test.go b/tests/utils_test.go
@@ -0,0 +1,113 @@
+package tests
+
+import (
+ "bytes"
+ "log"
+ "os"
+ "strings"
+ "testing"
+
+ "fingered/utils"
+)
+
+func TestIsValidWord(t *testing.T) {
+ validWords := []string{
+ "john", "alice", "bob", "dave",
+ "john123", "alice456", "dave789",
+ "john_doe", "alice_smith", "dave_jones",
+ }
+
+ invalidWords := []string{
+ "123", // Numbers only
+ "foo.bar", // Special characters
+ " ", // Empty string
+ "username=", // Potential injection…
+ "../", // Directory traversal
+ "/etc/passwd", // Absolute path trave…
+ "\\windows\\system32\\", // Windows path traver…
+ "ROOT", // Uppercase letters
+ "john_doe_", // Underscore at the e…
+ "john_doe_doe_doe_doe_doe_doe_doe_doe", // Too long
+ "foo|bar", // Shell pipe
+ "filename>.txt", // Shell redirection
+ "cmd &", // Background execution
+ "`ls -l`", // Command substitution
+ "$(echo hi)", // Command substitution
+ "{malicious}", // Command grouping
+ "evil$word", // Dollar sign
+ "abc;def", // Command chaining
+ "[evil]", // Command grouping
+ "nasty~word", // Tilde expansion
+ "question?", // Question mark
+ "exclamation!", // Exclamation mark
+ "\"quoted\"", // Double quotes
+ "'quoted'", // Single quotes
+ "escaped\\", // Backslash
+ }
+
+ for _, word := range validWords {
+ if !utils.IsValidWord(word) {
+ t.Errorf("isValidWord(%s) returned false, expected tru…
+ }
+ }
+
+ for _, word := range invalidWords {
+ if utils.IsValidWord(word) {
+ t.Errorf("isValidWord(%s) returned true, expected fals…
+ }
+
+ }
+}
+
+func TestGetContent(t *testing.T) {
+ // Create a temporary shell script file for testing
+ scriptContent := "#!/bin/sh\n\necho 'Hello, World!'"
+ scriptFile, err := os.CreateTemp("", "test_script_*.sh")
+ if err != nil {
+ t.Fatalf("Failed to create temporary script file: %v", err)
+ }
+ defer os.Remove(scriptFile.Name())
+ defer scriptFile.Close()
+
+ _, err = scriptFile.WriteString(scriptContent)
+ if err != nil {
+ t.Fatalf("Failed to write to temporary script file: %v", err)
+ }
+
+ tests := []struct {
+ filePath string
+ expected string
+ }{
+ {"nonexistent.txt", "file not found"},
+ {scriptFile.Name(), "Hello, World!\n"},
+ }
+
+ for _, test := range tests {
+ actual, err := utils.GetContent(test.filePath)
+ if err != nil {
+ if actual != test.expected {
+ t.Errorf("For file %s, expected '%s', but got …
+ }
+ }
+
+ if actual != test.expected {
+ t.Errorf("For file %s, expected '%s', but got '%s'", t…
+ }
+ }
+}
+
+func TestLogMsg(t *testing.T) {
+ var buf bytes.Buffer
+ log.SetOutput(&buf)
+ defer func() {
+ log.SetOutput(os.Stderr)
+ }()
+
+ utils.LogMsg("Test message: %s %d", "Hello", 123)
+ logOutput := buf.String()
+ expectedLogMessage := "Test message: Hello 123"
+
+ if !strings.Contains(logOutput, expectedLogMessage) {
+ t.Errorf("Log message does not contain the expected message. G…
+ }
+}
diff --git a/utils/utils.go b/utils/utils.go
@@ -0,0 +1,66 @@
+package utils
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "unicode"
+)
+
+func LogMsg(format string, args ...interface{}) {
+ message := fmt.Sprintf(format, args...)
+ log.Print(message)
+}
+
+func GetContent(filePath string) (string, error) {
+ _, err := os.Stat(filePath)
+ if os.IsNotExist(err) {
+ return "file not found", err
+ }
+
+ content, err := os.ReadFile(filePath)
+ if err != nil {
+ return "unable to read file", err
+ }
+
+ isScript := false
+ if len(content) > 2 && string(content[:3]) == "#!/" {
+ isScript = true
+ }
+
+ if isScript {
+ cmd := exec.Command("sh", filePath)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return "file execution failed", err
+ }
+ return string(output), nil
+ }
+
+ return string(content), nil
+}
+
+func WriteResponse(conn net.Conn, response string) (string, error) {
+ _, err := conn.Write([]byte(response))
+ if err != nil {
+ return "failed to write to socket", err
+ }
+
+ return "", nil
+}
+
+func IsValidWord(input string) bool {
+ if len(input) < 1 || len(input) > 32 || !unicode.IsLower(rune(input[0]…
+ return false
+ }
+
+ for _, r := range input {
+ if !(unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_') {
+ return false
+ }
+ }
+
+ return input[len(input)-1] != '_'
+}
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.